Quelle est la différence entre persist () et merge () dans JPA et Hibernate?

119

Quelle est la différence entre persist () et merge () dans Hibernate?

persist() peut créer une requête UPDATE & INSERT, par exemple:

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
A a=new A();
session.persist(a);
a.setName("Mario");
session.flush();

dans ce cas, la requête sera générée comme ceci:

Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?

donc la persist()méthode peut générer une insertion et une mise à jour.

Maintenant avec merge():

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

Voici ce que je vois dans la base de données:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti

Maintenant, mettez à jour un enregistrement en utilisant merge()

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setId(2);
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

Voici ce que je vois dans la base de données:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
Débardeur Jimit
la source
7
Le javadoc est très explicite sur ce qu'ils font et quelles sont les différences. L'avez-vous lu et compris?
skaffman
1
Vérifiez stackoverflow.com/questions/161224/…
Jigar Joshi

Réponses:

144

La spécification JPA contient une description très précise de la sémantique de ces opérations, mieux que dans javadoc:

La sémantique de l' opération persist , appliquée à une entité X est la suivante:

  • Si X est une nouvelle entité, elle devient gérée. L'entité X sera entrée dans la base de données à ou avant la validation de la transaction ou à la suite de l'opération de vidage.

  • Si X est une entité gérée préexistante, elle est ignorée par l'opération persist. Cependant, l'opération de persistance est mise en cascade sur les entités référencées par X, si les relations de X vers ces autres entités sont annotées avec la valeur de l'élément d'annotation cascade=PERSISTou cascade=ALLou spécifiées avec l'élément de descripteur XML équivalent.

  • Si X est une entité supprimée, elle devient gérée.

  • Si X est un objet détaché, le EntityExistsExceptionpeut être levé lorsque l'opération de persistance est appelée, ou le EntityExistsExceptionou un autre PersistenceExceptionpeut être levé au moment du vidage ou de la validation.

  • Pour toutes les entités Y référencées par une relation de X, si la relation avec Y a été annotée avec la valeur de l'élément en cascade cascade=PERSISTou cascade=ALL, l'opération de persistance est appliquée à Y.


La sémantique de l' opération de fusion appliquée à une entité X est la suivante:

  • Si X est une entité détachée, l'état de X est copié sur une instance d'entité gérée préexistante X 'de la même identité ou une nouvelle copie gérée X' de X est créée.

  • Si X est une nouvelle instance d'entité, une nouvelle instance d'entité gérée X 'est créée et l'état de X est copié dans la nouvelle instance d'entité gérée X'.

  • Si X est une instance d'entité supprimée, un IllegalArgumentExceptionsera levé par l'opération de fusion (ou la validation de transaction échouera).

  • Si X est une entité gérée, elle est ignorée par l'opération de fusion, cependant, l'opération de fusion est mise en cascade aux entités référencées par des relations de X si ces relations ont été annotées avec la valeur d'élément en cascade cascade=MERGEou l' cascade=ALLannotation.

  • Pour toutes les entités Y référencées par des relations de X ayant la valeur d'élément en cascade cascade=MERGEou cascade=ALL, Y est fusionné récursivement en tant que Y '. Pour tous ces Y référencés par X, X 'est mis à la référence Y'. (Notez que si X est géré alors X est le même objet que X '.)

  • Si X est une entité fusionnée avec X ', avec une référence à une autre entité Y, où cascade=MERGEou cascade=ALLn'est pas spécifié, alors la navigation de la même association à partir de X' produit une référence à un objet géré Y 'avec la même identité persistante que Y.

axtavt
la source
Merci pour l'info. Je vois la sémantique des deux définitions. Mais la question porte sur les différences entre eux. Présentez peut-être la liste des états et 2 sous-sections pour chaque comportement différent de persistvs merge?
AlikElzin-kilaka
25

Cela vient de JPA. D'une manière très simple:

  • persist(entity) doit être utilisé avec des entités totalement nouvelles, pour les ajouter à la base de données (si l'entité existe déjà dans la base de données, il y aura un lancer EntityExistsException).

  • merge(entity) doit être utilisé pour remettre l'entité dans le contexte de persistance si l'entité a été détachée et modifiée.

Krystian
la source
pouvez-vous s'il vous plaît ajouter une source à votre explication? Merci.
AlikElzin-kilaka
@ AlikElzin-kilaka une telle explication, si je me souviens bien, j'ai trouvé dans un livre "Beginning Java EE 7".
Krystian
12

Persist ne doit être appelé que sur les nouvelles entités, tandis que la fusion est destinée à rattacher les entités détachées.

Si vous utilisez le générateur attribué, l' utilisation de merge au lieu de persist peut entraîner une instruction SQL redondante , affectant ainsi les performances.

En outre, appeler la fusion pour les entités gérées est également une erreur car les entités gérées sont automatiquement gérées par Hibernate et leur état est synchronisé avec l'enregistrement de la base de données par le mécanisme de vérification sale lors du vidage du contexte de persistance .

Vlad Mihalcea
la source
1

La différence la plus importante est la suivante:

  • En cas de persistméthode, si l'entité à gérer dans le contexte de persistance existe déjà dans le contexte de persistance, la nouvelle est ignorée. (Rien ne s'est passé)

  • Mais en cas de mergeméthode, l'entité déjà gérée en contexte de persistance sera remplacée par la nouvelle entité (mise à jour) et une copie de cette entité mise à jour sera renvoyée. (à partir de maintenant, toutes les modifications doivent être apportées sur cette entité retournée si vous souhaitez refléter vos modifications dans le contexte de persistance)

Od Chan
la source