174 votes

Quelle est la différence entre session.persist() et session.save() dans Hibernate ?

Quelqu'un peut-il me dire quel est l'avantage de persist() vs save() dans Hibernate ?

10 votes

Voir aussi : Quel est l'avantage de load() par rapport à get() dans Hibernate ? stackoverflow.com/questions/5370482/

0 votes

C'est l'un des dernières réponses à ce jour par Vlad Mihalcea, l'auteur lui-même. Après avoir parcouru plusieurs anciens fils de discussion sur la documentation, la doc officielle et de nombreuses variantes sur Stack Overflow, voici l'une des réponses les mieux rassemblées avec des extraits. Ce site lien contient également les états du cycle de vie de l'entité, au cas où vous en auriez besoin.

164voto

Bala R Points 57552

De ce message du forum

persist() est bien défini. Il rend une instance transitoire persistante. Cependant, il ne garantit pas que la valeur de l'identifiant sera attribuée à l'instance persistante immédiatement, l'affectation peut se faire au moment de la chasse d'eau au moment du flush. La spécification ne le dit pas. est le problème que j'ai avec persist() .

persist() garantit également qu'il n'exécutera pas une instruction INSERT si elle est appelée en dehors des limites transaction. Ceci est utile dans conversations de longue durée avec un contexte de session/persistance étendu.

Une méthode comme persist() est nécessaire.

save() ne garantit pas la même chose, il renvoie un identifiant, et si un INSERT doit être exécuté pour obtenir l'identifiant identifiant (par exemple le générateur "identity", pas "séquence"), cet INSERT est exécuté immédiatement, peu importe si vous êtes l'intérieur ou l'extérieur d'une transaction. Ce n'est pas une bonne chose dans une conversation avec une session/contexte de persistance.

47 votes

Pour en ajouter d'autres du même poste, pour se plaindre : "Malheureusement, 5 ans plus tard, ce fil de discussion reste toujours la seule source d'information claire sur ce sujet. La documentation d'Hibernate, bien que verbeuse, est vide de toutes les informations d'utilisation, sauf les plus triviales. Pourquoi le dernier message de Christian n'est pas dans la javadoc de la session est un autre mystère de la documentation d'Hibernate."

0 votes

Vous voulez dire que la méthode persist() mettra l'entité dans un état détaché et la méthode save() dans un état attaché ?

4 votes

J'ai récemment utilisé les fonctions save et persist dans un mappage bidirectionnel de type one-to-many. J'ai découvert que save ne se répercute pas sur l'enfant, c'est-à-dire que seul Parent est sauvegardé/inséré dans la table. Cependant, j'ai réussi à sauvegarder le parent et l'enfant en un seul appel. J'utilise un ID composite et non un ID généré.

83voto

Zeus Points 1643

J'ai fait des recherches approfondies sur la méthode save() vs. persist(), notamment en l'exécutant plusieurs fois sur ma machine locale. Toutes les explications précédentes sont confuses et incorrectes. Je compare les méthodes save() et persist() ci-dessous après une recherche approfondie.

Save()

  1. Renvoie l'identité générée après l'enregistrement. Son type de retour est Serializable ;
  2. Enregistre les modifications dans la base de données en dehors de la transaction ;
  3. Affecte l'identifiant généré à l'entité que vous faites persister ;
  4. session.save() pour un objet détaché créera une nouvelle ligne dans le tableau.

Persist()

  1. Ne renvoie pas l'identité générée après la sauvegarde. Son type de retour est void ;
  2. N'enregistre pas les modifications dans la base de données en dehors de la transaction ;
  3. Affecte l'identifiant généré à l'entité que vous faites persister ;
  4. session.persist() pour un objet détaché lancera un PersistentObjectException car cela n'est pas autorisé.

Tous ces éléments sont testés sur Hibernate v4.0.1 .

0 votes

Le point 3 pour Save() et Persist() sont mentionnés mais ils ne sont pas réellement les mêmes. La méthode Persist() sauvegarde les changements dans la base de données en dehors de la transaction.

2 votes

Lorsque j'ai testé après avoir validé la transaction en utilisant la méthode persist, la valeur n'est pas enregistrée dans la base de données.

0 votes

Donc les numéros 1 et 5 sont la vraie différence entre les deux ? Si vous avez besoin qu'un identifiant soit retourné ou qu'une nouvelle ligne soit créée, utilisez Save() ?

25voto

J'ai fait quelques tests simulés pour enregistrer la différence entre save() y persist() .

Il semble que ces deux méthodes se comportent de la même manière lorsqu'il s'agit d'une entité transitoire, mais diffèrent lorsqu'il s'agit d'une entité détachée.

Dans l'exemple ci-dessous, prenons EmployeeVehicle comme entité avec PK en tant que vehicleId qui est une valeur générée et vehicleName comme l'une de ses propriétés.

Exemple 1 : Traitement d'un objet transitoire

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

Résultat :

select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

Notez que le résultat est le même lorsque vous récupérez un objet déjà persistant et que vous le sauvegardez.

EmployeeVehicle entity =  (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity);    -------> **instead of session.update(entity);**
// session.persist(entity);

Répétez l'opération en utilisant persist(entity) et le résultat sera le même avec une nouvelle Id ( disons 37 , honda ) ;

Exemple 2 : Traitement d'un objet détaché

// Session 1 
// Get the previously saved Vehicle Entity 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached object 
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();

Résultat : Vous pourriez vous attendre à ce que le véhicule avec l'id : 36 obtenu dans la session précédente soit mis à jour avec le nom "Toyota". Mais ce qui se passe, c'est qu'une nouvelle entité est sauvegardée dans la base de données avec le nouvel ID généré pour et le nom "Toyota".

select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

Utilisation de persist pour persister une entité détachée

// (ii) Using Persist()  to persist a detached
// Session 1 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();

Résultat :

Exception being thrown : detached entity passed to persist

Ainsi, il est toujours préférable d'utiliser Persist() plutôt que Save() car Save doit être utilisé avec précaution lorsqu'il s'agit d'objets transitoires.

Note importante : Dans l'exemple ci-dessus, le pk de l'entité véhicule est une valeur générée, donc quand on utilise save() pour persister une entité détachée, Hibernate génère un nouvel id à persister. Cependant, si ce pk n'est pas une valeur générée, il en résulte une exception indiquant que la clé est violée.

15voto

CFL_Jeff Points 1043

Cette question contient de bonnes réponses sur les différentes méthodes de persistance dans Hibernate. Pour répondre directement à votre question, avec save(), l'instruction d'insertion est exécutée immédiatement, quel que soit l'état de la transaction. Elle renvoie la clé insérée, ce qui vous permet de faire quelque chose comme ceci :

long newKey = session.save(myObj);

Utilisez donc save() si vous avez besoin d'un identifiant attribué à l'instance persistante immédiatement.

Avec persist(), l'instruction d'insertion est exécutée dans une transaction, pas nécessairement immédiatement. C'est préférable dans la plupart des cas.

Utilisez persist() si vous n'avez pas besoin que l'insertion soit

7voto

David Pham Points 732

Voici les différences qui peuvent vous aider à comprendre les avantages des méthodes de persistance et de sauvegarde :

  • La première différence entre save et persist est leur type de retour. L'adresse type de retour de la méthode persist est void tandis que le type de retour de save
    est un objet Serializable.

  • La méthode persist() ne garantit pas que la valeur de l'identifiant sera sera assignée à l'état persistant immédiatement, l'assignation pourrait se produire au moment du flush.

  • La méthode persist() n'exécutera pas une requête d'insertion si elle est appelée en dehors des limites de la transaction. Par contre, la méthode save() renvoie un identifiant afin qu'une requête d'insertion soit exécutée immédiatement pour obtenir l'identifiant, peu importe qu'il soit à l'intérieur ou à l'extérieur d'une transaction.

  • La méthode persist est appelée en dehors des limites de la transaction, elle est utile dans les conversations de longue durée avec un contexte de étendue. D'un autre côté, la méthode save n'est pas utile dans une conversation avec un contexte de session étendu.

  • Cinquième différence entre les méthodes save et persist dans Hibernate : persist est supportée par JPA, alors que save n'est supportée que par Hibernate.

Vous pouvez voir l'exemple complet de travail à partir de l'article. Différence entre les méthodes save et persist dans Hibernate

0 votes

Vous dites d'abord "La méthode persist() n'exécutera pas une requête d'insertion si elle est appelée en dehors des limites de la transaction". Puis vous dites "La méthode persist est appelée en dehors des limites de la transaction, elle est utile dans les conversations de longue durée avec un contexte de session étendu." Ne sont-elles pas contradictoires ? Je ne comprends pas.

0 votes

@KumarManish Dans le cas de la méthode persist, une requête d'insertion se produit au moment du flush. Il s'agit donc d'une bonne pratique pour les conversations de longue durée.

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