Perché JPA ha un'annotazione @Transient?


Risposte:


455

La transientparola chiave Java viene utilizzata per indicare che un campo non deve essere serializzato, mentre l' @Transientannotazione di JPA viene utilizzata per indicare che un campo non deve essere persistito nel database, vale a dire che la loro semantica è diversa.


3
Sì, la semantica è diversa. Ma perché l'APP è stato progettato in questo modo?
Dilum Ranatunga,

1
Non sono sicuro di capirti, ma dai un'occhiata alla risposta di "Pascal Thivent";)
Jawher,

30
Ciò è utile perché potresti non voler archiviare i dati nel database, ma desideri archiviarli nel sistema di Chaching JPA che utilizza la serializzazione per l'archiviazione / il ripristino di entità.
Kdeveloper,

1
Quale "sistema di memorizzazione nella cache JPA" che utilizza la serializzazione per l'archiviazione / il ripristino di entità? un'implementazione JPA può memorizzare nella cache un oggetto come desidera e la serializzazione non entra in esso.
DataNucleus,

@Jawher, qui per transitorio non presente significa non presistere alcun valore o inserirà il valore predefinito per quell'attributo.
Satish Sharma,

115

Perché hanno significati diversi. L' @Transientannotazione indica al provider JPA di non persistere alcun transientattributo (non ). L'altro dice al framework di serializzazione di non serializzare un attributo. Potresti voler avere una @Transientproprietà e comunque serializzarla.


Grazie per la risposta Pascal. Come nota dal tuo commento: "Potresti voler avere una proprietà @Transient e comunque serializzarla". (Era quello che stavo cercando) Voglio anche aggiungere che il contrario non è vero. Se si imposta una variabile come transitoria, non è possibile persisterla.
jfajunior,

96

Come altri hanno già detto, @Transientviene utilizzato per contrassegnare i campi che non devono essere mantenuti. Considera questo breve esempio:

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);
    }
}

Quando questa classe è alimentato all'APP, persiste la gendere idma non tenta di persistere metodi booleani helper - senza @Transientil sistema sottostante si lamentano che la classe Entity Personè mancante setMale()e setFemale()metodi e quindi non sarebbe persistere Personaffatto.


@psp puoi spiegare di più sul perché / come potrebbe causare comportamenti non specificati? Grazie!
Taiduckman,

@ 40Plot specifica la specifica
psp

7
Questa dovrebbe essere la risposta accettata
dall'IMHO in

53

Lo scopo è diverso:

La transientparola chiave e l' @Transientannotazione hanno due scopi diversi: uno si occupa della serializzazione e uno si occupa della persistenza . Come programmatori, spesso sposiamo questi due concetti in uno solo, ma questo non è accurato in generale. La persistenza si riferisce alla caratteristica dello stato che sopravvive al processo che l'ha creata. La serializzazione in Java si riferisce al processo di codifica / decodifica dello stato di un oggetto come flusso di byte.

La transientparola chiave è una condizione più forte di @Transient:

Se un campo utilizza la transientparola chiave, quel campo non verrà serializzato quando l'oggetto viene convertito in un flusso di byte. Inoltre, poiché l'APP considera i campi contrassegnati con la transientparola chiave come aventi l' @Transientannotazione, neanche l'APP persevererà nel campo.

D'altra parte, i campi annotati @Transientda soli verranno convertiti in un flusso di byte quando l'oggetto è serializzato, ma non verrà persistito da JPA. Pertanto, la transientparola chiave è una condizione più forte @Transientdell'annotazione.

Esempio

Ciò pone la domanda: perché qualcuno dovrebbe voler serializzare un campo che non è persistito nel database dell'applicazione? La realtà è che la serializzazione viene utilizzata per qualcosa di più della semplice persistenza . In un'applicazione Java Enterprise deve esserci un meccanismo per scambiare oggetti tra componenti distribuiti ; la serializzazione fornisce un protocollo di comunicazione comune per gestirlo. Pertanto, un campo può contenere informazioni critiche ai fini della comunicazione tra componenti; ma quello stesso campo potrebbe non avere alcun valore dal punto di vista della persistenza.

Ad esempio, supponiamo che un algoritmo di ottimizzazione venga eseguito su un server e supponga che questo algoritmo richieda diverse ore per essere completato. Per un cliente è importante disporre delle soluzioni più aggiornate. Pertanto, un client può iscriversi al server e ricevere aggiornamenti periodici durante la fase di esecuzione dell'algoritmo. Questi aggiornamenti vengono forniti utilizzando l' ProgressReportoggetto:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

La Solutionclasse potrebbe apparire così:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

Il server persiste ciascuno ProgressReportnel suo database. Il server non si preoccupa di persistere estimatedMinutesRemaining, ma il client ha sicuramente a cuore queste informazioni. Pertanto, estimatedMinutesRemainingviene annotato usando @Transient. Quando la finale Solutionviene individuata dall'algoritmo, viene mantenuta direttamente da JPA senza utilizzare a ProgressReport.


1
Se in realtà sono preoccupazioni diverse, sicuramente esiste una parola diversa che cattura le sfumature. Perché sovraccaricare il termine? Come suggerimento antipasto, @Unpersisted.
Dilum Ranatunga,

4
Personalmente mi piace @Ephemeral. Secondo Merriam Webster: Quando l'effimero fu stampato per la prima volta in inglese nel 1600, "era un termine scientifico applicato alle febbri a breve termine e, successivamente, agli organismi (come insetti e fiori) con una durata della vita molto breve. Poco dopo , acquisì un senso esteso riferendosi a qualsiasi cosa fugace e di breve durata (come nei "piaceri effimeri"). "
Austin D,

1
Quello che mi piace anche di questa risposta è che menziona il fatto che l'APP considera i transientcampi implicitamente aventi l' @Transientannotazione. Quindi, se si utilizza la transientparola chiave per impedire la serializzazione di un campo, non finirà nemmeno nel database.
NeXus,

17

Se vuoi solo che un campo non sia persistente, funzionano sia i transitori che i @Transient . Ma la domanda è perché @Transient da quando esiste il transitorio .

Perché il campo @Transient verrà comunque serializzato!

Supponiamo di creare un'entità, facendo alcuni calcoli che consumano CPU per ottenere un risultato e questo risultato non verrà salvato nel database. Ma vuoi inviare l'entità ad altre applicazioni Java da utilizzare da JMS, quindi dovresti usare @Transient, non la parola chiave JavaSE transient. Pertanto, i ricevitori in esecuzione su altre macchine virtuali possono risparmiare tempo per ricalcolare di nuovo.


puoi per favore fornire un esempio per renderlo più chiaro?
Harsh Kanakhara

c'è un'annotazione che jpa tratterà come transitoria, ma Jackson no?
Kalpesh Soni,

0

Proverò a rispondere alla domanda "perché". Immagina una situazione in cui hai un enorme database con molte colonne in una tabella e il tuo progetto / sistema usa strumenti per generare entità dal database. (Hibernate ha quelli, ecc ...) Ora, supponiamo che secondo la vostra logica aziendale sia necessario che un particolare campo NON sia persistente. Devi "configurare" la tua entità in un modo particolare. Mentre la parola chiave Transient funziona su un oggetto, poiché si comporta in un linguaggio java, @Transient è progettato solo per rispondere alle attività che riguardano solo le attività di persistenza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.