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

新手上路,请多包涵

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

persist() 可以创建更新和插入查询,例如:

 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

原文由 Jimit Tank 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

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

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

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

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

  • 如果 X 是一个已删除的实体,它就会变成托管的。

  • 如果 X 是分离的对象,则在调用持久化操作时可能抛出 EntityExistsException ,或者可能抛出 EntityExistsException 或另一个 PersistenceException 时间。

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


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

  • 如果 X 是分离的实体,则 X 的状态被复制到具有相同身份的预先存在的托管实体实例 X’ 或创建 X 的新托管副本 X’。

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

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

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

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

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

原文由 axtavt 发布,翻译遵循 CC BY-SA 2.5 许可协议

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

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

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

原文由 Krystian 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题