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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (13)

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()方法可以生成一个Insert和一个Update。

现在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
提问于
用户回答回答于

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

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

  • 如果X是一个新的实体,它就会被管理。实体X将在事务提交时或之前进入数据库或作为刷新操作的结果。
  • 如果X是一个先前存在的管理实体,它会被持久操作忽略。但是,如果从X到这些其他实体的关系使用cascade=PERSISTor cascade=ALL annotation元素值进行注释,或者使用等效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则合并操作将抛出(或事务提交将失败)。
  • 如果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'的引用。

用户回答回答于

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

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

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

扫码关注云+社区