web-dev-qa-db-fra.com

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

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 requête sera généré comme ceci:

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

alors la méthode persist() 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
115
Jimit Tank

spécification JPA contient une description très précise de la sémantique de ces opérations, meilleure 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 au plus tard à 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 de persistance. Cependant, l'opération persist est mise en cascade vers les entités référencées par X, si les relations de X avec ces autres entités sont annotées avec le signe cascade=PERSIST ou cascade=ALL valeur d'élément d'annotation ou spécifiée 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 EntityExistsException peut être levé lorsque l'opération de persistance est appelée ou le EntityExistsException ou un autre PersistenceException peut être levé au moment de la purge ou de la validation.

  • Pour toutes les entités Y référencées par une relation de X, si la relation à Y a été annotée avec la valeur de l'élément en cascade cascade=PERSIST ou 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 IllegalArgumentException sera émis par l'opération de fusion (ou la validation de la transaction échouera).

  • Si X est une entité gérée, elle est ignorée par l'opération de fusion. Toutefois, l'opération de fusion est mise en cascade vers les entités référencées par les relations à partir de X si ces relations ont été annotées avec la valeur de l'élément en cascade cascade=MERGE ou cascade=ALL annotation.

  • Pour toutes les entités, Y est référencé par des relations à partir de X ayant la valeur de l'élément en cascade cascade=MERGE ou cascade=ALL, Y est fusionné de manière récursive en tant que Y '. Pour tous ces Y référencés par X, X 'est défini pour référencer Y'. (Notez que si X est géré, 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=MERGE ou cascade=ALL n'est pas spécifié, la navigation de la même association à partir de X 'renvoie une référence à un objet géré Y' avec la même identité persistante que Y.

142
axtavt

Cela vient de JPA. De manière très simple:

persist (entité) 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 une entité EntityExistsException).

fusionner (entité) doit être utilisé pour remettre l'entité en contexte de persistance si l'entité a été détachée et modifiée.

22
Krystian

La persistance doit être appelée uniquement sur les nouvelles entités, alors que la fusion est destinée à rattacher les entités détachées.

Si vous utilisez le générateur affecté, tiliser la fusion au lieu de persist peut provoquer une instruction SQL redondante , affectant ainsi les performances.

En outre, fusion d'appel 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 à blanc après - effacement du contexte de persistance .

11
Vlad Mihalcea

la différence la plus importante est la suivante: En cas d'utilisation de la méthode persist, 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 méthode de fusion, l'entité déjà gérée dans un 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, toute modification doit être apportée à cette entité renvoyée si vous souhaitez refléter vos modifications dans le contexte de persistance)

1
Od Chan