В чем разница между persist () и merge () в JPA и Hibernate? - PullRequest
115 голосов
/ 22 декабря 2010

В чем разница между 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

Ответы [ 4 ]

142 голосов
/ 22 декабря 2010

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

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

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

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

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

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

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


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

  • Если X является отсоединенным объектом, состояние X копируется в ранее существующий экземпляр управляемого объекта X 'та же личность или new создается управляемая копия X 'of 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.

22 голосов
/ 04 ноября 2015

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

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

Следует использовать слияние (сущность), чтобы вернуть сущность обратно в контекст постоянства, если сущность была отсоединена и была изменена.

11 голосов
/ 19 июля 2016

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

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

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

1 голос
/ 17 апреля 2019

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

...