JPA和Hibernate中persist()和merge()有什么区别?

Jim*_*ank 115 java orm entity hibernate jpa

Hibernate中persist()和merge()有什么区别?

persist() 可以创建UPDATE和INSERT查询,例如:

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

在这种情况下,查询将生成如下:

Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?
Run Code Online (Sandbox Code Playgroud)

所以persist()方法可以生成插入和更新.

现在merge():

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

这是我在数据库中看到的:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti
Run Code Online (Sandbox Code Playgroud)

现在使用更新记录 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();
Run Code Online (Sandbox Code Playgroud)

这是我在数据库中看到的:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
Run Code Online (Sandbox Code Playgroud)

axt*_*avt 142

JPA规范包含对这些操作的语义的非常精确的描述,比javadoc更好:

应用于实体X 的持久化操作的语义如下:

  • 如果X是一个新实体,它就会被管理.实体X将在事务提交时或之前或作为刷新操作的结果输入数据库.

  • 如果X是预先存在的托管实体,则persist操作会忽略它.但是,如果从X到这些其他实体的关系使用cascade=PERSISTcascade=ALL 注释元素值注释或使用等效的XML描述符元素指定,则持久化操作将级联到X引用的实体 .

  • 如果X是已删除的实体,则它将被管理.

  • 如果X是一个分离的对象,则 EntityExistsException可以在调用持久化操作时抛出,或者可以在刷新或提交时抛出该EntityExistsException另一个或另一个PersistenceException.

  • 通过从X的关系中引用的所有实体Y,如果Y的关系已经被注释与级联元件值 cascade=PERSISTcascade=ALL,persist操作被施加到Y.


应用于实体X 的合并操作的语义如下:

  • 如果X是分离的实体,则将X的状态复制到具有相同标识的预先存在的管理实体实例X'上,或者创建X的新管理副本X'.

  • 如果X是新的实体实例,则创建新的管理实体实例X',并且将X的状态复制到新的管理实体实例X'中.

  • 如果X是已删除的实体实例,IllegalArgumentException则合并操作将抛出一个 (或者事务提交将失败).

  • 如果X是一个托管实体,它将被合并操作忽略,但是,如果这些关系已使用级联元素值cascade=MERGEcascade=ALL注释进行注释,则合并操作将级联到由X的关系引用的实体.

  • 对于具有级联元素值的X的关系所引用的所有实体Y,cascade=MERGE或者cascade=ALLY被递归地合并为Y'.对于由X引用的所有这样的Y,X'被设置为引用Y'.(注意,如果管理X,那么X与X'是同一个对象.)

  • 如果X是合并到X'的实体,并且引用另一个实体Y,其中cascade=MERGE或未cascade=ALL指定,则从X'导航相同的关联产生对具有与Y相同的持久标识的被管理对象Y'的引用.


Kry*_*ian 23

这来自JPA.以一种非常简单的方式:

persist(entity)应该与全新的实体一起使用,将它们添加到DB中(如果实体已经存在于DB中,则会抛出EntityExistsException).

应该使用merge(实体),如果实体已分离并已更改,则将实体放回持久性上下文.


Vla*_*cea 12

应该仅在新实体上调用Persist,而merge用于重新附加分离的实体.

如果您使用的是已分配的生成器,则使用merge而不是persist会导致冗余的SQL语句,从而影响性能.

此外,为托管实体调用合并也是一个错误,因为托管实体由Hibernate自动管理,并且在刷新持久性上下文时,它们的状态通过脏检查机制与数据库记录同步.

  • 是的,在提交之前,会进行自动刷新,除非您使用只读会话或 Tx。 (2认同)