首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在JPA和Hibernate中persist()和merge()有什么区别?

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

Stack Overflow用户
提问于 2010-12-22 20:20:22
回答 4查看 170.3K关注 0票数 126

Hibernate中persist()和merge()有什么不同?

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

代码语言:javascript
复制
SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
A a=new A();
session.persist(a);
a.setName("Mario");
session.flush();

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

代码语言:javascript
复制
Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?

因此persist()方法可以生成、插入和更新。

现在使用merge()

代码语言:javascript
复制
SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

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

代码语言:javascript
复制
SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti

现在使用merge()更新一条记录

代码语言:javascript
复制
SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setId(2);
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

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

代码语言:javascript
复制
SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-12-22 20:57:07

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

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

  • 如果X是一个新实体,它将成为托管实体。实体X将在事务提交时或之前或作为刷新操作的结果输入到数据库中。
  • 如果X是预先存在的托管实体,则持久化操作将忽略它。但是,如果从X到这些其他实体的关系是用cascade=PERSISTcascade=ALL注释元素值注释的,或者是用等效的XML描述符元素指定的,则持久化操作将级联到X引用的实体。
  • 如果X是已移除的实体,则它将成为托管实体。
  • 如果X是分离的对象,则在调用持久化操作时可能会抛出EntityExistsException。对于X中的关系引用的所有实体Y,如果与Y的关系已用级联元素值cascade=PERSISTcascade=ALL进行了批注,则
  • 操作将应用于Y。

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

  • 如果X是分离的实体,则将X的状态复制到具有相同身份的预先存在的受管实体实例X‘上,或者创建X的新的受管副本X’。
  • 如果X是新的实体实例,则创建新的受管实体实例X‘,并且将X的状态复制到新的受管实体实例X’中。
  • 如果X是移除的实体实例,合并操作将引发IllegalArgumentException (否则事务提交将失败)。
  • 如果X是托管实体,则合并操作将忽略它,但是,如果X中的关系已使用级联元素值cascade=MERGEcascade=ALL对这些关系进行了批注,则合并操作将级联到这些关系引用的实体。如果X中的关系引用的所有实体Y都具有级联元素值cascade=MERGEcascade=ALL,则Y将递归合并为Y‘。对于X引用的所有这样的Y,X‘被设置为引用Y’。(请注意,如果X是托管的,则X与X‘是相同的对象。)
  • 如果X是合并到X’的实体,则引用另一个实体Y,其中未指定cascade=MERGEcascade=ALL,则从X‘导航相同的关联将产生对具有与Y相同的持久标识的托管对象Y’的引用。
票数 149
EN

Stack Overflow用户

发布于 2015-11-04 20:40:39

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

  • persist(entity)应该与全新的实体一起使用,以将它们添加到数据库中(如果实体已经存在于数据库中,则会抛出EntityExistsException )。如果实体被分离并更改,则应使用
  • merge(entity)将实体放回持久性上下文。
票数 28
EN

Stack Overflow用户

发布于 2016-07-19 16:35:44

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

如果您使用的是指定的生成器,那么使用merge而不是persist可能会导致冗余的SQL语句。

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

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4509086

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档