Dlaczego JPA ma adnotację @Transient?


Odpowiedzi:


455

Słowo transientkluczowe Javy służy do oznaczania, że ​​pole nie ma być serializowane, natomiast @Transientadnotacja JPA służy do wskazania, że ​​pole nie ma być utrwalane w bazie danych, tj. Ich semantyka jest inna.


3
Tak, semantyka jest inna. Ale dlaczego JPA zostało zaprojektowane w ten sposób?
— Dilum Ranatunga

1
Nie jestem pewien, czy cię rozumiem, ale spójrz na odpowiedź „Pascala Thiventa”;)
— Jawher

30
Jest to przydatne, ponieważ możesz nie chcieć przechowywać danych w bazie danych, ale chcesz je przechowywać w systemie JPA Chaching, który używa serializacji do przechowywania / przywracania jednostek.
— Kdeveloper,

1
Jaki „system buforowania JPA” wykorzystujący serializację do przechowywania / przywracania jednostek? implementacja JPA może buforować obiekt w dowolny sposób, a serializacja nie wchodzi w niego.
— DataNucleus,

@Jawher, tutaj dla przejściowych, nieprezydentujących oznacza, że ​​nie należy presistować żadnej wartości, albo wstawi wartość domyślną dla tego atrybutu.
— Satish Sharma

115

Ponieważ mają różne znaczenia. @TransientAdnotacja informuje dostawcę JPA nie utrzymują żadnego (nie transient) atrybut. Drugi informuje środowisko serializacji, aby nie serializowało atrybutu. Możesz chcieć mieć @Transientwłaściwość i nadal ją serializować.


Dzięki za odpowiedź Pascal. Jako notatkę z komentarza: „Możesz mieć właściwość @Transient i nadal ją przekształcać do postaci szeregowej”. (Właśnie tego szukałem). Chcę również dodać, że przeciwieństwo nie jest prawdą. Jeśli ustawimy zmienną jako przejściową, to nie będzie można jej zachować.
— jfajunior

96

Jak powiedzieli inni, @Transientsłuży do oznaczania pól, których nie należy utrwalać. Rozważ ten krótki przykład:

public enum Gender { MALE, FEMALE, UNKNOWN }

@Entity
public Person {
    private Gender g;
    private long id;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }

    public Gender getGender() { return g; }    
    public void setGender(Gender g) { this.g = g; }

    @Transient
    public boolean isMale() {
        return Gender.MALE.equals(g);
    }

    @Transient
    public boolean isFemale() {
        return Gender.FEMALE.equals(g);
    }
}

Gdy ta klasa jest podawana do JPA, trwa genderi idnie próbuje utrwalić metod pomocniczych boolean - bez @Transientsystemu bazowego narzekałby, że Personbrakuje klasy Entity setMale()i setFemale()metod, a zatem nie trwałby Personwcale.


@psp. Czy możesz wyjaśnić, dlaczego / jak może to powodować nieokreślone zachowanie? Dzięki!
— taiduckman,

@ 40Plot stwierdza, że ​​tak
— psp

7
To powinna być IMHO zaakceptowana odpowiedź, ponieważ znacznie bardziej wyjaśnia, że ​​obecnie przyjęta odpowiedź ...
— Honza Zidek

53

Cel jest inny:

Słowo transientkluczowe i @Transientadnotacja mają dwa różne cele: jeden dotyczy serializacji, a drugi uporczywości . Jako programiści często łączymy te dwie koncepcje w jedną, ale ogólnie nie jest to dokładne. Trwałość odnosi się do cechy państwa, która przeżywa proces, który go stworzył. Serializacja w Javie odnosi się do procesu kodowania / dekodowania stanu obiektu jako strumienia bajtów.

Słowo transientkluczowe jest silniejszym warunkiem niż @Transient:

Jeśli pole używa transientsłowa kluczowego, pole to nie będzie serializowane, gdy obiekt zostanie przekonwertowany na strumień bajtów. Ponadto, ponieważ JPA traktuje pola oznaczone transientsłowem kluczowym jako opatrzone @Transientadnotacją, JPA również nie utrwali tego pola.

Z drugiej strony, pola z adnotacjami @Transientsame zostaną przekonwertowane na strumień bajtów, gdy obiekt zostanie zserializowany, ale JPA nie utrwali go. Dlatego transientsłowo kluczowe jest silniejszym warunkiem niż @Transientadnotacja.

Przykład

To nasuwa pytanie: dlaczego ktokolwiek miałby chcieć serializować pole, które nie jest utrwalone w bazie danych aplikacji? Rzeczywistość jest taka, że serializacja służy nie tylko do wytrwałości . W aplikacji Enterprise Java musi istnieć mechanizm wymiany obiektów między rozproszonymi komponentami ; serializacja zapewnia wspólny protokół komunikacyjny do obsługi tego. Zatem pole może zawierać informacje krytyczne do celów komunikacji między komponentami; ale to samo pole może nie mieć żadnej wartości z perspektywy trwałości.

Załóżmy na przykład, że algorytm optymalizacji jest uruchomiony na serwerze i załóżmy, że ten algorytm zajmuje kilka godzin. Dla klienta ważne jest posiadanie najnowocześniejszego zestawu rozwiązań. Tak więc klient może subskrybować serwer i otrzymywać okresowe aktualizacje podczas fazy wykonywania algorytmu. Te aktualizacje są dostarczane za pomocą ProgressReportobiektu:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

SolutionKlasa może wyglądać następująco:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

Serwer utrzymuje każdy ProgressReportz nich w swojej bazie danych. Serwer nie chce się utrzymywać estimatedMinutesRemaining, ale klient z pewnością dba o te informacje. Dlatego estimatedMinutesRemainingjest opatrzony adnotacją przy użyciu @Transient. Gdy finał Solutionjest zlokalizowany przez algorytm, jest on utrwalany przez JPA bezpośrednio bez użycia ProgressReport.


1
Jeśli faktycznie są to różne obawy, z pewnością istnieje inne słowo, które oddaje niuanse. Po co przeciążać termin? Jako sugestię Starter @Unpersisted.
— Dilum Ranatunga

4
Ja osobiście lubię @Ephemeral. Według Merriam Webster: Kiedy efemeria została po raz pierwszy wydrukowana w języku angielskim w 1600 roku, „był to termin naukowy stosowany do krótkotrwałych gorączek, a później do organizmów (takich jak owady i kwiaty) o bardzo krótkim okresie życia. Wkrótce potem , nabrał rozszerzonego sensu odnoszącego się do wszystkiego, co przelotne i krótkotrwałe (jak w „efemerycznych przyjemnościach”). ”
— Austin D

1
W tej odpowiedzi podoba mi się również to, że wspomina, że ​​JPA uważa transientpola za pośrednio @Transientopatrzone adnotacją. Jeśli więc użyjesz transientsłowa kluczowego, aby zapobiec serializacji pola, to również nie trafi ono do bazy danych.
— neXus

17

Jeśli chcesz tylko pola nie będzie się utrzymywał, zarówno przemijające i @Transient pracy. Ale pytanie brzmi: dlaczego @Transient, ponieważ transient już istnieje.

Ponieważ pole @Transient nadal będzie serializowane!

Załóżmy, że tworzysz encję, wykonując pewne obliczenia pochłaniające procesor, aby uzyskać wynik, a wynik ten nie zostanie zapisany w bazie danych. Ale chcesz wysłać encję do innych aplikacji Java do użycia przez JMS, wtedy powinieneś użyć @Transient, a nie słowa kluczowego JavaSE transient. Dzięki temu odbiorniki działające na innych maszynach wirtualnych mogą zaoszczędzić czas na ponowne obliczenia.


czy możesz podać przykład, aby wyjaśnić?
— Harsh Kanakhara

czy jest adnotacja, że ​​jpa będzie traktowane jako przejściowe, ale Jackson nie będzie?
— Kalpesh Soni

0

Spróbuję odpowiedzieć na pytanie „dlaczego”. Wyobraź sobie sytuację, w której masz ogromną bazę danych z dużą ilością kolumn w tabeli, a Twój projekt / system używa narzędzi do generowania jednostek z bazy danych. (Hibernacja ma takie, itp ...) Załóżmy teraz, że zgodnie z logiką biznesową potrzebujesz określonego pola, aby NIE można było go utrwalić. Musisz „skonfigurować” swój byt w określony sposób. Podczas gdy słowo kluczowe Transient działa na obiekcie - ponieważ zachowuje się w języku Java, @Transient służy wyłącznie do odpowiadania na zadania dotyczące tylko zadań związanych z trwałością.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.