在JPA和Hibernate中,persist()和merge()之间有什么区别?


119

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();

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

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

7
Javadoc非常明确地说明了它们的作用以及区别。您阅读并理解了吗?
skaffman 2010年


Answers:


144

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

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

  • 如果X是新实体,则它将成为托管实体。实体X将在事务提交之时或之前或作为刷新操作的结果输入数据库中。

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

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

  • 如果X是一个分离的对象,则 EntityExistsException当persist操作被调用时,或者可能抛出EntityExistsException或另一个PersistenceException可在冲洗被抛出或提交时间。

  • 对于由X的关系引用的所有实体Y,如果与Y的关系已用级联元素值cascade=PERSIST或注释 cascade=ALL,则将持久操作应用于Y。


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

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

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

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

  • 如果X是受管实体,则合并操作将忽略它,但是,如果已用级联元素值cascade=MERGEcascade=ALL注释对这些关系进行了注释,则合并操作将级联到X的关系所引用的实体。

  • 对于由具有级联元素值cascade=MERGE或的X的关系引用的所有实体Y cascade=ALL,将Y递归合并为Y'。对于X引用的所有此类Y,将X'设置为引用Y'。(请注意,如果管理X,则X与X'是同一对象。)

  • 如果X是一个实体合并X”,与基准向另一个实体Y,其中cascade=MERGEcascade=ALL未指定指定),则从X'导航相同的关联会生成对具有与Y相同的持久标识的托管对象Y'的引用。


谢谢(你的)信息。我看到了两个定义的语义。但是问题在于它们之间的差异。也许为persistvs的每个不同行为提供状态列表和2个小节merge
AlikElzin-kilaka'3

25

这是来自JPA。以非常简单的方式:

  • persist(entity) 应该与全新实体一起使用,以将其添加到数据库中(如果实体已经存在于数据库中,则将抛出EntityExistsException异常)。

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


您可以在说明中添加资料来源吗?谢谢。
AlikElzin-kilaka'3

我记得,@ AlikElzin-kilaka这样的解释是在《 Beginning Java EE 7》一书中找到的。
Krystian


1

最重要的区别是:

  • persist方法的情况下,如果要在持久性上下文中管理的实体已经存在于持久性上下文中,则将忽略新的实体。(什么都没有发生)

  • 但是在使用merge方法的情况下,已经在持久性上下文中管理的实体将被新实体替换(更新),并且此更新实体的副本将返回。(从现在开始,如果要在持久性上下文中反映您的更改,则应对此返回的实体进行任何更改)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.