Pourquoi JPA a-t-il une annotation @Transient?

283

Java a le transientmot - clé. Pourquoi JPA a-t-il @Transientau lieu d'utiliser simplement le mot-clé java déjà existant?

démon
la source

Réponses:

455

Le transientmot - clé Java est utilisé pour indiquer qu'un champ ne doit pas être sérialisé, tandis que l' @Transientannotation JPA est utilisée pour indiquer qu'un champ ne doit pas être conservé dans la base de données, c'est-à-dire que leur sémantique est différente.

Jawher
la source
3
Oui, la sémantique est différente. Mais pourquoi JPA a-t-il été conçu de cette façon?
Dilum Ranatunga
1
Je ne suis pas sûr de bien vous comprendre, mais jetez un œil à la réponse de "Pascal Thivent";)
Jawher
30
Ceci est pratique car vous ne souhaiterez peut-être pas stocker les données dans la base de données, mais vous souhaitez les stocker dans le système JPA Chaching qui utilise la sérialisation pour le stockage / la restauration des entités.
Kdeveloper
1
Quel «système de mise en cache JPA» qui utilise la sérialisation pour stocker / restaurer des entités? une implémentation JPA peut mettre en cache un objet comme il le souhaite, et la sérialisation n'y entre pas.
DataNucleus
@Jawher, ici pour transitoire non présistant signifie ne pas conserver de valeur ou il insérera la valeur par défaut pour cet attribut.
Satish Sharma
115

Parce qu'ils ont des significations différentes. L' @Transientannotation indique au fournisseur JPA de ne conserver aucun transientattribut (non ). L'autre indique au framework de sérialisation de ne pas sérialiser un attribut. Vous voudrez peut-être avoir une @Transientpropriété et toujours la sérialiser.

Pascal Thivent
la source
Merci pour la réponse Pascal. Comme une note de votre commentaire: "Vous voudrez peut-être avoir une propriété @Transient et toujours la sérialiser." (C'est ce que je cherchais) Je veux également ajouter que le contraire n'est pas vrai. Si l'on définit une variable comme transitoire, vous ne pouvez pas la conserver.
jfajunior
96

Comme d'autres l'ont dit, @Transientest utilisé pour marquer des champs qui ne doivent pas être conservés. Considérez ce court exemple:

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

Lorsque cette classe est envoyée à la JPA, elle persiste genderet idn'essaie pas de persister les méthodes booléennes auxiliaires - sans que @Transientle système sous-jacent ne se plaigne que la classe Entity Personest manquante setMale()et que les setFemale()méthodes ne persisteraient donc pas Persondu tout.

Esko
la source
@psp pouvez-vous expliquer davantage pourquoi / comment cela pourrait provoquer un comportement non spécifié? Merci!
taiduckman
@ 40 Tracer les états de spécification ainsi
psp
7
Cela devrait être à mon humble avis la réponse acceptée car elle explique beaucoup plus que celle actuellement acceptée ...
Honza Zidek
53

Le but est différent:

Le transientmot-clé et l' @Transientannotation ont deux objectifs différents: l'un traite de la sérialisation et l'autre de la persistance . En tant que programmeurs, nous marions souvent ces deux concepts en un seul, mais ce n'est pas exact en général. La persistance se réfère à la caractéristique de l'État qui survit au processus qui l'a créé. La sérialisation en Java fait référence au processus de codage / décodage de l'état d'un objet en tant que flux d'octets.

Le transientmot-clé est une condition plus solide que @Transient:

Si un champ utilise le transientmot clé, ce champ ne sera pas sérialisé lorsque l'objet est converti en un flux d'octets. De plus, étant donné que JPA traite les champs marqués avec le transientmot - clé comme ayant l' @Transientannotation, le champ ne sera pas non plus conservé par JPA.

En revanche, les champs annotés @Transientseuls seront convertis en un flux d'octets lorsque l'objet est sérialisé, mais il ne sera pas conservé par JPA. Par conséquent, le transientmot clé est une condition plus forte que l' @Transientannotation.

Exemple

Cela soulève la question: pourquoi quelqu'un voudrait-il sérialiser un champ qui n'est pas conservé dans la base de données de l'application? La réalité est que la sérialisation est utilisée pour plus que de la persistance . Dans une application Enterprise Java, il doit y avoir un mécanisme pour échanger des objets entre les composants distribués ; la sérialisation fournit un protocole de communication commun pour gérer cela. Ainsi, un champ peut contenir des informations critiques à des fins de communication entre composants; mais ce même champ peut n'avoir aucune valeur du point de vue de la persistance.

Par exemple, supposons qu'un algorithme d'optimisation soit exécuté sur un serveur et supposons que cet algorithme prenne plusieurs heures. Pour un client, disposer de l'ensemble de solutions le plus à jour est important. Ainsi, un client peut s'abonner au serveur et recevoir des mises à jour périodiques pendant la phase d'exécution de l'algorithme. Ces mises à jour sont fournies à l'aide de l' ProgressReportobjet:

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

La Solutionclasse pourrait ressembler à ceci:

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

Le serveur persiste chacun ProgressReportdans sa base de données. Le serveur ne tient pas à persister estimatedMinutesRemaining, mais le client se soucie certainement de ces informations. Par conséquent, le estimatedMinutesRemainingest annoté à l'aide de @Transient. Lorsque la finale Solutionest localisée par l'algorithme, elle est conservée directement par JPA sans utiliser a ProgressReport.

Austin D
la source
1
S'il s'agit en réalité de préoccupations différentes, il existe sûrement un mot différent qui capture les nuances. Pourquoi surcharger le terme? Comme suggestion de démarrage, @Unpersisted.
Dilum Ranatunga
4
J'aime personnellement @Ephemeral. Selon Merriam Webster: Quand l'éphémère a été imprimé pour la première fois en anglais dans les années 1600, "c'était un terme scientifique appliqué aux fièvres à court terme, et plus tard, aux organismes (tels que les insectes et les fleurs) avec des durées de vie très courtes. , il a acquis un sens étendu se référant à tout ce qui est éphémère et éphémère (comme dans les "plaisirs éphémères"). "
Austin D
1
Ce que j'aime aussi dans cette réponse, c'est qu'elle mentionne que JPA considère les transientchamps comme ayant implicitement l' @Transientannotation. Donc, si vous utilisez le transientmot - clé pour empêcher la sérialisation d'un champ, il ne se retrouvera pas non plus dans la base de données.
neXus
17

Si vous voulez juste qu'un champ ne persiste pas, les deux transitoires et @Transient fonctionnent. Mais la question est de savoir pourquoi @Transient car transitoire existe déjà.

Parce que le champ @Transient sera toujours sérialisé!

Supposons que vous créez une entité, en faisant des calculs consommant beaucoup de CPU pour obtenir un résultat et ce résultat ne sera pas enregistré dans la base de données. Mais si vous souhaitez envoyer l'entité à d'autres applications Java à utiliser par JMS, vous devez utiliser @Transient, pas le mot clé JavaSE transient. Ainsi, les récepteurs fonctionnant sur d'autres machines virtuelles peuvent gagner du temps pour recalculer à nouveau.

Sheng.W
la source
pouvez-vous s'il vous plaît fournir un exemple pour le rendre plus clair?
Harsh Kanakhara
Y a-t-il une annotation que jpa traitera comme transitoire mais pas jackson?
Kalpesh Soni
0

Je vais essayer de répondre à la question du "pourquoi". Imaginez une situation où vous avez une énorme base de données avec beaucoup de colonnes dans une table, et votre projet / système utilise des outils pour générer des entités à partir de la base de données. (Hibernate en a, etc ...) Maintenant, supposons que selon votre logique métier, vous avez besoin qu'un champ particulier ne soit PAS persisté. Vous devez "configurer" votre entité d'une manière particulière. Alors que le mot-clé Transient fonctionne sur un objet - car il se comporte dans un langage java, le @Transient est uniquement conçu pour répondre aux tâches qui ne concernent que les tâches de persistance.

Dima R.
la source