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