340 votes

Pourquoi JPA dispose-t-il d'une annotation @Transient ?

Java dispose de la transient mot-clé. Pourquoi JPA a-t-il @Transient au lieu d'utiliser simplement le mot-clé java qui existe déjà ?

536voto

Jawher Points 1932

Le système Java transient est utilisé pour indiquer qu'un champ ne doit pas être sérialisé, alors que le mot-clé @Transient 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.

3 votes

Oui, la sémantique est différente. Mais pourquoi JPA a-t-il été conçu de cette manière ?

1 votes

Je ne suis pas sûr de vous comprendre, mais jetez un coup d'œil à la réponse de "Pascal Thivent" ;)

36 votes

C'est pratique parce que vous ne voulez peut-être pas stocker les données dans la base de données, mais vous voulez les stocker dans le système de mise en cache JPA qui utilise la sérialisation pour le stockage/la restauration des entités.

130voto

Pascal Thivent Points 295221

Parce qu'ils ont des significations différentes. Les @Transient indique au fournisseur JPA de ne pas persister les données (non transient ). L'autre indique au cadre de sérialisation de ne pas sérialiser un attribut. Il peut être utile d'avoir un attribut @Transient et le sérialiser quand même.

1 votes

Merci pour la réponse Pascal. Une note de votre commentaire : "Vous pourriez vouloir avoir une propriété @Transient tout en la sérialisant." (C'est ce que je cherchais) Je voudrais aussi ajouter que le contraire n'est pas vrai. Si l'on définit une variable comme transitoire, on ne peut pas la conserver.

118voto

Esko Points 15578

Comme d'autres l'ont dit, @Transient est utilisé pour marquer les champs qui ne doivent pas être conservés. Prenons 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 transmise à la JPA, elle persiste dans l'élément gender y id mais n'essaie pas de persister les méthodes booléennes d'aide - sans @Transient le système sous-jacent se plaindrait que la classe Entity Person manque setMale() y setFemale() et ne persisterait donc pas Person du tout.

0 votes

@psp pouvez-vous expliquer plus en détail pourquoi/comment cela pourrait causer un comportement non spécifié ? Je vous remercie de votre attention.

0 votes

@40Plot le cahier des charges le stipule

8 votes

Cette réponse devrait être acceptée, car elle est beaucoup plus explicite que la réponse actuellement acceptée...

71voto

Austin D Points 1968

L'objectif est différent :

En transient mot-clé et @Transient ont deux objectifs différents : l'un concerne les sérialisation et l'autre concerne persistance . En tant que programmeurs, nous fusionnons souvent ces deux concepts en un seul, mais ce n'est pas le cas en général. Persistance désigne la caractéristique d'un état qui survit au processus qui l'a créé. Sérialisation en Java fait référence au processus de codage/décodage de l'état d'un objet sous la forme d'un flux d'octets.

En transient Le mot-clé est une condition plus forte que le mot-clé @Transient :

Si un champ utilise l'option transient ce champ ne sera pas sérialisé lorsque l'objet sera converti en flux d'octets. En outre, étant donné que JPA traite les champs marqués par le mot-clé transient comme ayant le mot-clé @Transient le champ ne sera pas non plus conservé par JPA.

En revanche, les champs annotés @Transient seul volonté sera converti en flux d'octets lors de la sérialisation de l'objet, mais il ne sera pas conservé par JPA. Par conséquent, l'objet transient est une condition plus forte que le mot-clé @Transient annotation.

Exemple

La question se pose donc : Pourquoi voudrait-on sérialiser un champ qui n'est pas persisté dans la base de données de l'application ? La réalité est que la sérialisation n'est pas seulement utilisée pour la persistance . Dans une application Java d'entreprise, il faut qu'il y ait un mécanisme d'échange d'objets entre composants distribués ; la sérialisation fournit un protocole de communication commun pour gérer cela. Ainsi, un champ peut contenir des informations critiques pour la 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 que cet algorithme prenne plusieurs heures. Pour un client, il est important de disposer de l'ensemble de solutions le plus récent. Un client peut donc 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 la fonction ProgressReport objet :

@Entity
public class ProgressReport implements Serializable{

    private static final long serialVersionUID = 1L;

    @Transient
    long estimatedMinutesRemaining;
    String statusMessage;
    Solution currentBestSolution;

}

En Solution pourrait ressembler à ceci :

@Entity
public class Solution implements Serializable{

    private static final long serialVersionUID = 1L;

    double[][] dataArray;
    Properties properties;
}

Le serveur conserve chaque ProgressReport à sa base de données. Le serveur ne se préoccupe pas de persister estimatedMinutesRemaining mais le client est certainement intéressé par ces informations. Par conséquent, le estimatedMinutesRemaining est annoté à l'aide de @Transient . Lorsque la décision finale Solution est localisé par l'algorithme, il est persisté par JPA directement sans utiliser un fichier ProgressReport .

23voto

Sheng.W Points 1932

Si vous souhaitez simplement qu'un champ ne soit pas persisté, les deux méthodes suivantes peuvent être utilisées transitoire y @Transient travail. Mais la question est de savoir pourquoi @Transient depuis transitoire existe déjà.

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

Supposons que vous créiez une entité, que vous fassiez un calcul consommateur d'énergie pour obtenir un résultat et que ce résultat ne soit pas sauvegardé dans la base de données. Mais vous voulez envoyer l'entité à d'autres applications Java pour qu'elle soit utilisée par JMS, alors vous devez utiliser @Transient et non le mot-clé JavaSE transient . Ainsi, les récepteurs fonctionnant sur d'autres machines virtuelles peuvent gagner du temps pour refaire les calculs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X