В чем разница между session.Merge и session.SaveOrUpdate?

Иногда я замечаю, что с моими родительскими / дочерними объектами или отношениями «многие ко многим» мне нужно вызвать либо SaveOrUpdate, либо Merge. Обычно, когда мне нужно вызвать SaveOrUpdate, исключение, которое я получаю при вызове Merge, связано с тем, что временные объекты не сохраняются в первую очередь.

Пожалуйста, объясните разницу между ними.


person EvilSyn    schedule 04.10.2008    source источник


Ответы (6)


Это из раздела 10.7. Автоматическое определение состояния Справочной документации по Hibernate:

saveOrUpdate () выполняет следующие действия:

  • если объект уже является постоянным в этом сеансе, ничего не делать
  • если другой объект, связанный с сеансом, имеет тот же идентификатор, генерировать исключение
  • если объект не имеет свойства идентификатора, save () его
  • если идентификатор объекта имеет значение, присвоенное вновь созданному объекту, save () его
  • если для объекта установлена ​​версия (с помощью ‹version› или ‹timestamp›), а значение свойства версии совпадает со значением, присвоенным вновь созданному объекту, save () его
  • в противном случае update () объект

и merge () очень разные:

  • если существует постоянный экземпляр с тем же идентификатором, который в настоящее время связан с сеансом, скопируйте состояние данного объекта на постоянный экземпляр
  • если в данный момент нет постоянного экземпляра, связанного с сеансом, попробуйте загрузить его из базы данных или создайте новый постоянный экземпляр
  • постоянный экземпляр возвращается
  • данный экземпляр не становится связанным с сеансом, он остается отключенным

Вам следует использовать Merge (), если вы пытаетесь обновить объекты, которые в какой-то момент были отсоединены от сеанса, особенно если могут существовать постоянные экземпляры тех объектов, которые в настоящее время связаны с сеансом. В противном случае использование SaveOrUpdate () в этом случае приведет к исключению.

person David Crow    schedule 04.10.2008
comment
хороший ответ ... Интересно - если я использую слияние для нового объекта, есть ли причина для использования послесловия сохранения, или я могу предположить, что слияние точно создало новый объект в БД? (а если это отдельный объект, после слияния изменения автоматически пропадают в БД?) - person Dani; 30.11.2009
comment
Ты уверен насчет этого? При просмотре источника NHiberante SaveOrUpdateCopy запускает событие Merge с теми же параметрами, что и функция Merge. Я думаю, что они идентичны, функция SaveOrUpdateCopy - это то, что существует в hibernate / nhibernate с 1.0, функция Merge является новой и была добавлена ​​в спящий режим, чтобы соответствовать новому стандарту java (я думаю) - person Torkel; 04.01.2010
comment
@Torkel - SaveOrUpdateCopy - это не то же самое, что SaveOrUpdate. Я не уверен, хотел ли спрашивающий сравнить Merge первое или второе. SaveOrUpdateCopy - это уже устаревший метод, который выполнял слияние в NHibernate до импорта Merge. - person codekaizen; 13.04.2011
comment
Полезно знать ... SaveOrUpdate все еще активно используется в учебных пособиях. - person anael; 13.04.2011

Насколько я понимаю, merge() возьмет объект, который может не быть связан с текущим сеансом, и скопирует его состояние (значения свойств и т. Д.) В объект, который связан с текущим сеансом (с то же значение / идентификатор PK, конечно).

saveOrUpdate() вызовет Сохранить или Обновить в вашем сеансе в зависимости от значения идентификатора данного объекта.

person Ryan Duffield    schedule 04.10.2008

SaveOrUpdateCopy() устарел в NHibernate 3.1. Вместо этого следует использовать Merge().

person Ricardo Peres    schedule 05.04.2011
comment
Это SaveOrUpdateCopy, отмеченное знаком Obsolete, а не SaveOrUpdate. Кажется, существует большая путаница между этими двумя разными методами в этом вопросе и последующих ответах. - person codekaizen; 13.04.2011

** Update()**

: - если вы уверены, что сеанс не содержит уже постоянного экземпляра с тем же идентификатором, используйте обновление, чтобы сохранить данные в спящем режиме

** Merge()**

: -если вы хотите сохранить свои изменения в любое время, не зная о состоянии сеанса, используйте merge () в спящем режиме.

person Mohit Singh    schedule 20.04.2015

Я нашел эту ссылку, которая довольно хорошо объяснила этот тип исключения:

Для меня сработало следующее:

  1. В файле сопоставления Myclass.hbm.xml установите cascade="merge"
  2. SaveOrUpdate сначала дочерний / зависимый объект, прежде чем назначить его родительскому объекту.
  3. SaveOrUpdate родительский объект.

Однако у этого решения есть ограничения. то есть вы должны позаботиться о сохранении вашего дочернего / зависимого объекта вместо того, чтобы позволить спящему режиму делать это за вас.

Если у кого-то есть лучшее решение, я бы хотел посмотреть.

person Quoc Truong    schedule 17.02.2014

person    schedule
comment
Вам следует подумать о редактировании своего ответа, чтобы показать выполненный код, а затем, возможно, рассмотреть полный дамп кода в конце. В его нынешнем виде мы должны прокрутить вниз и случайно просмотреть комментарии. См. Как ответить. - person Bugs; 28.04.2017