Détails
JPA EntityManager : Pourquoi utiliser persist() plutôt que merge() ?
EntityManager.merge()
peut insérer de nouveaux objets et mettre à jour les objets existants.
Pourquoi voudrait-on utiliser persist()
(qui ne peut que créer de nouveaux objets) ?
920
3
L'une ou l'autre de ces méthodes permet d'ajouter une entité à un PersistenceContext. La différence réside dans ce que vous faites ensuite de l'entité.
Persist prend une instance d'entité, l'ajoute au contexte et rend cette instance gérée (c'est-à-dire que les futures mises à jour de l'entité seront suivies).
Merge crée une nouvelle instance de votre entité, copie l'état de l'entité fournie, et rend la nouvelle copie gérée. L'instance que vous transmettez ne sera pas gérée (les modifications que vous apportez ne feront pas partie de la transaction - à moins que vous n'appeliez à nouveau merge).
Un exemple de code pourrait peut-être vous aider.
Les scénarios 1 et 3 sont à peu près équivalents, mais il y a certaines situations où vous voudriez utiliser le scénario 2.
J'ai remarqué que lorsque j'utilisais
em.merge
, j'obtenais une instructionSELECT
pour chaqueINSERT
, même s'il n'y avait aucun champ que JPA générait pour moi - le champ de la clé primaire était un UUID que j'avais moi-même défini. Je suis passé àem.persist(myEntityObject)
et je n'ai eu que des instructionsINSERT
.Je recevais des exceptions lazyLoading sur mon entité parce que j'essayais d'accéder à une collection chargée paresseusement qui était en session.
Dans une requête séparée, je récupérais l'entité dans la session, puis j'essayais d'accéder à une collection dans ma page jsp, ce qui posait problème.
Pour pallier à ce problème, j'ai mis à jour la même entité dans mon contrôleur et je l'ai passée à mon jsp, bien que j'imagine que lorsque j'ai réenregistré en session, elle sera également accessible via
SessionScope
et ne lancera pas uneLazyLoadingException
, une modification de l'exemple 2 :Ce qui suit a fonctionné pour moi :