В чем разница между persist () и merge () в JPA и Hibernate?

119

В чем разница между persist () и merge () в Hibernate?

persist() может создать запрос UPDATE & INSERT, например:

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

в этом случае запрос будет сгенерирован так:

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

так что persist()метод может генерировать вставку и обновление.

Теперь с merge():

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

Вот что я вижу в базе данных:

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

Теперь обновите запись, используя 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();

Вот что я вижу в базе данных:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
Джимит Танк
источник
7
В javadoc очень четко указано, что они делают и в чем различия. Вы это прочитали и поняли?
skaffman
1
Проверьте stackoverflow.com/questions/161224/…
Джигар Джоши

Ответы:

144

Спецификация JPA содержит очень точное описание семантики этих операций, лучше, чем в javadoc:

Семантика операции сохранения , примененной к сущности X, следующая:

  • Если X - новый объект, он становится управляемым. Сущность X будет введена в базу данных во время или до фиксации транзакции или в результате операции очистки.

  • Если X - уже существующий управляемый объект, он игнорируется операцией сохранения. Тем не менее, сохраняется операция каскад к объектам , на которые ссылаются X, если отношения с X в эти другие сущности аннотированные с cascade=PERSISTили cascade=ALL значением аннотации элемента или указанный с эквивалентным XML дескриптором элементом.

  • Если X - удаленный объект, он становится управляемым.

  • Если X является отсоединенным объектом, EntityExistsExceptionможет быть брошен при вызове операции сохранения, или тот EntityExistsExceptionили иной PersistenceExceptionможет быть брошен во время сброса или фиксации.

  • Для всех сущностей Y, на которые ссылается отношение из X, если отношение к Y было аннотировано значением каскадного элемента cascade=PERSISTили cascade=ALLк Y применяется операция сохранения.


Семантика операции слияния, применяемой к объекту X, следующая:

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

  • Если X является новым экземпляром объекта, создается новый экземпляр X 'управляемого объекта, и состояние X копируется в новый экземпляр X' управляемого объекта.

  • Если X - удаленный экземпляр сущности, IllegalArgumentExceptionоперация слияния будет выброшена (или фиксация транзакции завершится ошибкой).

  • Если X является управляемой сущностью, она игнорируется операцией слияния, однако операция слияния каскадно передается сущностям, на которые ссылаются отношения из X, если эти отношения были аннотированы значением cascade=MERGEили cascade=ALLаннотацией каскадного элемента .

  • Для всех сущностей Y, на которые ссылаются отношения из X, имеющие значение каскадного элемента cascade=MERGEили cascade=ALL, Y объединяется рекурсивно как Y '. Для всех таких Y, на которые ссылается X, X 'устанавливается как ссылка Y'. (Обратите внимание, что если X управляется, то X является тем же объектом, что и X '.)

  • Если X - это объект, объединенный с X ', со ссылкой на другой объект Y, где cascade=MERGEили cascade=ALLне указан, то переход по той же ассоциации из X' дает ссылку на управляемый объект Y 'с тем же постоянным идентификатором, что и Y.

axtavt
источник
Спасибо за информацию. Я вижу семантику обоих определений. Но вопрос в различиях между ними. Может быть, представить список состояний и 2 подраздела для каждого типа поведения persistvs merge?
AlikElzin-kilaka 06
25

Это исходит от JPA. Очень просто:

  • persist(entity) следует использовать с совершенно новыми объектами, чтобы добавить их в БД (если объект уже существует в БД, будет выброшено исключение EntityExistsException).

  • merge(entity) следует использовать, чтобы вернуть объект в контекст персистентности, если объект был отсоединен и изменен.

Krystian
источник
не могли бы вы добавить источник к своему объяснению? Спасибо.
AlikElzin-kilaka 06
@ AlikElzin-kilaka такое объяснение, насколько я помню, я нашел в книге "Beginning Java EE 7".
Krystian
12

Persist следует вызывать только для новых сущностей, в то время как слияние предназначено для повторного присоединения отдельных сущностей.

Если вы используете назначенный генератор, использование слияния вместо сохранения может вызвать избыточный оператор SQL , что повлияет на производительность.

Кроме того, вызов слияния для управляемых сущностей также является ошибкой, поскольку управляемые сущности автоматически управляются Hibernate, и их состояние синхронизируется с записью базы данных с помощью механизма грязной проверки при сбросе контекста постоянства .

Влад Михалча
источник
1

Самое важное отличие заключается в следующем:

  • В случае persistметода, если объект, которым нужно управлять в контексте постоянства, уже существует в контексте постоянства, новый игнорируется. (Ничего не произошло)

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

Од Чан
источник