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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

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