Dlaczego JPA ma adnotację @Transient?

283

Java ma transientsłowo kluczowe. Dlaczego JPA @Transientzamiast zwyczajnie używać już istniejącego słowa kluczowego Java?

deamon
źródło

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.

Jawher
źródło
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ć.

Pascal Thivent
źródło
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.

Esko
źródło
@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.

Austin D.
źródło
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.

Sheng.W
źródło
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ą.

Dima R.
źródło