[英]What is the difference between persist() and merge() in JPA and Hibernate?
What is the difference between persist() and merge() in Hibernate? Hibernate 中的persist() 和merge() 有什么区别?
persist()
can create a UPDATE & INSERT query, eg: persist()
可以创建一个 UPDATE & INSERT 查询,例如:
SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
A a=new A();
session.persist(a);
a.setName("Mario");
session.flush();
in this case query will be generated like this:在这种情况下,查询将像这样生成:
Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?
so persist()
method can generate an Insert and an Update.所以
persist()
方法可以生成一个插入和一个更新。
Now with merge()
:现在使用
merge()
:
SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();
This is what I see in the database:这是我在数据库中看到的:
SINGER_ID SINGER_NAME
1 Ricky Martin
2 Madonna
3 Elvis Presley
4 Luciano Pavarotti
Now update a record using merge()
现在使用
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();
This is what I see in the database:这是我在数据库中看到的:
SINGER_ID SINGER_NAME
1 Ricky Martin
2 Luciano Pavarotti
3 Elvis Presley
JPA specification contains a very precise description of semantics of these operations, better than in javadoc: JPA 规范包含对这些操作语义的非常精确的描述,比 javadoc 中的要好:
The semantics of the persist operation, applied to an entity X are as follows:
应用于实体 X 的持久操作的语义如下:
If X is a new entity, it becomes managed.
如果 X 是一个新实体,它将成为托管。 The entity X will be entered into the database at or before transaction commit or as a result of the flush operation.
实体 X 将在事务提交时或之前或作为刷新操作的结果输入到数据库中。
If X is a preexisting managed entity, it is ignored by the persist operation.
如果 X 是预先存在的受管实体,则持久操作将忽略它。 However, the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities are annotated with the
cascade=PERSIST
orcascade=ALL
annotation element value or specified with the equivalent XML descriptor element.但是,如果从 X 到这些其他实体的关系使用
cascade=PERSIST
或cascade=ALL
注释元素值注释或使用等效的 XML 描述符元素指定,则持久操作级联到由 X 引用的实体。If X is a removed entity, it becomes managed.
如果 X 是已删除的实体,则它变为托管的。
If X is a detached object, the
EntityExistsException
may be thrown when the persist operation is invoked, or theEntityExistsException
or anotherPersistenceException
may be thrown at flush or commit time.如果X是一个分离的目的,
EntityExistsException
当persist操作被调用时,或者可能抛出EntityExistsException
或另一个PersistenceException
可以在冲洗被抛出或提交时间。For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value
cascade=PERSIST
orcascade=ALL
, the persist operation is applied to Y.对于由来自 X 的关系引用的所有实体 Y,如果与 Y 的关系已使用级联元素值
cascade=PERSIST
或cascade=ALL
进行注释,则对 Y 应用持久操作。
The semantics of the merge operation applied to an entity X are as follows:
应用于实体 X 的合并操作的语义如下:
If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X' of the same identity or a new managed copy X' of X is created.
如果 X 是分离的实体,则 X 的状态被复制到具有相同身份的预先存在的受管实体实例 X' 上,或者创建 X 的新受管副本 X'。
If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.
如果 X 是新的实体实例,则创建新的受管实体实例 X',并将 X 的状态复制到新的受管实体实例 X'。
If X is a removed entity instance, an
IllegalArgumentException
will be thrown by the merge operation (or the transaction commit will fail).如果 X 是已删除的实体实例,则合并操作将抛出
IllegalArgumentException
(否则事务提交将失败)。If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships from X if these relationships have been annotated with the cascade element value
cascade=MERGE
orcascade=ALL
annotation.如果 X 是受管实体,则合并操作将忽略它,但是,如果这些关系已使用级联元素值
cascade=MERGE
或cascade=ALL
注释,则合并操作级联到由来自 X 的关系引用的实体。For all entities Y referenced by relationships from X having the cascade element value
cascade=MERGE
orcascade=ALL
, Y is merged recursively as Y'.对于由来自 X 的关系引用的所有实体 Y 具有级联元素值
cascade=MERGE
或cascade=ALL
,Y 被递归合并为 Y'。 For all such Y referenced by X, X' is set to reference Y'.对于 X 引用的所有此类 Y,X' 设置为引用 Y'。 (Note that if X is managed then X is the same object as X'.)
(请注意,如果 X 是被管理的,那么 X 与 X' 是同一个对象。)
If X is an entity merged to X', with a reference to another entity Y, where
cascade=MERGE
orcascade=ALL
is not specified, then navigation of the same association from X' yields a reference to a managed object Y' with the same persistent identity as Y.如果 X 是合并到 X' 的实体,并引用另一个实体 Y,其中未指定
cascade=MERGE
或cascade=ALL
,则从 X' 导航相同关联会产生对托管对象 Y' 的引用与 Y 相同的持久身份。
This is coming from JPA
.这是来自
JPA
。 In a very simple way:以一种非常简单的方式:
persist(entity)
should be used with totally new entities, to add them to DB (if entity already exists in DB there will be EntityExistsException throw). persist(entity)
应该与全新的实体一起使用,将它们添加到 DB(如果 DB 中已经存在实体,则会抛出 EntityExistsException)。
merge(entity)
should be used, to put entity back to persistence context if the entity was detached and was changed.应该使用
merge(entity)
,如果实体被分离并被更改,则将实体放回持久性上下文。
Persist should be called only on new entities, while merge
is meant to reattach detached entities. Persist 应该只在新实体上调用,而
merge
意味着重新附加分离的实体。
If you're using the assigned generator, using merge
instead of persist
can cause a redundant SQL statement.如果您使用指定的生成器,使用
merge
而不是persist
可能会导致冗余的 SQL 语句。
Also, calling merge for managed entities is also a mistake since managed entities are automatically managed by Hibernate, and their state is synchronized with the database record by the dirty checking mechanism upon flushing the Persistence Context.此外,为托管实体调用合并也是一个错误,因为托管实体由 Hibernate 自动管理,并且它们的状态在刷新持久性上下文时通过脏检查机制与数据库记录同步。
The most important difference is this:最重要的区别是:
In case of persist
method, if the entity that is to be managed in the persistence context, already exists in persistence context, the new one is ignored.在
persist
方法的情况下,如果要在持久化上下文中管理的实体已经存在于持久化上下文中,则忽略新的实体。 (NOTHING happened) (什么都没有发生)
But in case of merge
method, the entity that is already managed in persistence context will be replaced by the new entity (updated) and a copy of this updated entity will return back.但是在
merge
方法的情况下,已经在持久化上下文中管理的实体将被新实体(更新)替换,并且这个更新实体的副本将返回。 (from now on any changes should be made on this returned entity if you want to reflect your changes in persistence context) (从现在开始,如果您想在持久性上下文中反映您的更改,则应对此返回的实体进行任何更改)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.