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

时间:2010-12-22 12:20:22

标签: java hibernate jpa orm entity

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

persist()可以创建更新& 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

4 个答案:

答案 0 :(得分:142)

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

  

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

     
      
  • 如果X是新实体,那么   变得有管理。实体X将是   在或之前进入数据库   事务提交或由于   冲洗操作。

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

  •   
  • 如果X是已移除的实体,   它变得有管理。

  •   
  • 如果X是a   分离的对象,   可能会抛出EntityExistsException   当调用持久化操作时,   或EntityExistsException或   另一个PersistenceException可能是   在刷新或提交时抛出。

  •   
  • 有关   a引用的所有实体Y.   来自X的关系,如果是   与Y的关系已被注释   具有级联元素值   cascade=PERSISTcascade=ALL,{。}}   持久操作适用于Y。

  •   

  

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

     
      
  • 如果X是分离的实体,则为状态   将X复制到预先存在的   管理实体实例X'相同   X的身份或新的托管副本X'   已创建。

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

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

  •   
  • 如果是X.   是一个托管实体,它被忽略   然而,合并操作   合并操作级联到   关系引用的实体   来自X,如果这些关系有   已经注册了级联   元素值cascade=MERGE或   cascade=ALL注释。

  •   
  • 对所有人来说   关系引用的实体Y.   来自X的具有级联元素   值cascade=MERGEcascade=ALL,Y   以Y'递归合并。对全部   这样的Y由X引用,X'设置为   参考Y'。 (注意,如果X是   管理然后X是与之相同的对象   X”)

  •   
  • 如果X是合并到X'的实体,   引用另一个实体Y,   cascade=MERGEcascade=ALL的位置   未指定,然后导航   来自X'的相同关联产生a   引用托管对象Y'   与Y相同的持久性身份。

  •   

答案 1 :(得分:21)

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

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

应使用

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

答案 2 :(得分:11)

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

如果您使用指定的生成器using merge instead of persist can cause a redundant SQL statement,则会影响性能。

此外,calling merge for managed entities也是一个错误,因为管理实体由Hibernate自动管理,并且dirty checking mechanismflushing the Persistence Context上状态与数据库记录同步。

答案 3 :(得分:1)

最重要的区别是: 在persist方法的情况下,如果要在持久性上下文中管理的实体已经存在于持久性上下文中,则将忽略新的实体。 (没啥事儿) 但是在采用合并方法的情况下,已经在持久性上下文中管理的实体将被新实体替换(更新),并且此更新实体的副本将返回。 (从现在开始,如果您想在持久性上下文中反映您的更改,则应该对此返回的实体进行任何更改)