web-dev-qa-db-fra.com

Quelle est la différence entre session.Merge et session.SaveOrUpdate?

Je remarque parfois avec mes objets parent/enfant ou des relations plusieurs-à-plusieurs, je dois appeler SaveOrUpdate ou Merge. Habituellement, lorsque j'ai besoin d'appeler SaveOrUpdate, l'exception que j'obtiens en appelant Merge concerne les objets transitoires qui ne sont pas enregistrés en premier.

Veuillez expliquer la différence entre les deux.

86
EvilSyn

Ceci provient de la section 10.7. Détection automatique de l'état de la documentation de référence Hibernate:

saveOrUpdate () effectue les opérations suivantes:

  • si l'objet est déjà persistant dans cette session, ne faites rien
  • si un autre objet associé à la session a le même identifiant, lève une exception
  • si l'objet n'a pas de propriété identifiant, enregistrez-le ()
  • si l'identifiant de l'objet a la valeur attribuée à un objet nouvellement instancié, enregistrez-le ()
  • si l'objet est versionné (par une <version> ou <timestamp>), et que la valeur de la propriété version est la même valeur attribuée à un objet nouvellement instancié, enregistrez-le ()
  • sinon mettre à jour () l'objet

et merge () est très différent:

  • s'il existe une instance persistante avec le même identifiant actuellement associé à la session, copiez l'état de l'objet donné sur l'instance persistante
  • si aucune instance persistante n'est actuellement associée à la session, essayez de la charger à partir de la base de données ou créez une nouvelle instance persistante
  • l'instance persistante est renvoyée
  • l'instance donnée ne devient pas associée à la session, elle reste détachée

Vous devez utiliser Merge () si vous essayez de mettre à jour des objets qui à un moment donné ont été détachés de la session, en particulier s'il peut y avoir des instances persistantes de ces objets actuellement associés à la session. Sinon, l'utilisation de SaveOrUpdate () dans ce cas entraînerait une exception.

156
David Crow

Si je comprends bien, merge() prendra un objet qui ne peut pas être associé à la session en cours et copiera son état (valeurs de propriété, etc.) dans un objet qui est associé à la session en cours (avec la même valeur PK/identifiant, bien sûr).

saveOrUpdate() appellera Save ou pdate sur votre session, en fonction de la valeur d'identité d'un objet donné.

9
Ryan Duffield

SaveOrUpdateCopy() est désormais obsolète depuis NHibernate 3.1. Merge() doit être utilisé à la place.

4
Ricardo Peres
** Update()**

: - si vous êtes sûr que la session ne contient pas d'instance déjà persistante avec le même identifiant alors utilisez update pour sauvegarder les données en hibernation

** Merge()**

: -si vous souhaitez sauvegarder vos modifications à tout moment sans connaître l'état d'une session, utilisez merge () en hibernate.

2
Mohit Singh

Nouvel identifiant utilisateur, je ne peux donc pas commenter ni voter sur le post de Quoc Truong. Cependant, je pense également que le lien est très utile comme indiqué précédemment.

http://www.roseindia.net/hibernate/hibernate4/org_hibernate_nonuniqueobjectexception.shtml

1
BoBoCoding

J'ai trouvé ce lien qui a fait un très bon travail expliquant ce type d'exception:

Ce qui a fonctionné pour moi est le suivant:

  1. Dans le fichier de mappage Myclass.hbm.xml, définissez cascade="merge"
  2. SaveOrUpdate l'objet enfant/dépendant avant de l'affecter à l'objet parent.
  3. SaveOrUpdate l'objet parent.

Cependant, cette solution a ses limites. c'est-à-dire que vous devez prendre soin de sauvegarder votre enfant/objet dépendant au lieu de laisser l'hibernation le faire pour vous.

Si quelqu'un a une meilleure solution, j'aimerais voir.

1
Quoc Truong