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

Java JPA和Hibernate中的persist()和merge()有什么区别?,java,hibernate,jpa,orm,entity,Java,Hibernate,Jpa,Orm,Entity,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 i

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

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

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti
SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
现在使用
merge()

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

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti
SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
包含对这些操作语义的非常精确的描述,优于javadoc:

的语义持续存在 操作,应用于实体X 详情如下:

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

  • 如果X是一个 先前存在的托管实体,它是 被持久化操作忽略。 但是,持久化操作是无效的 级联到X引用的实体, 如果从X到这些 其他实体用
    cascade=PERSIST
    cascade=ALL
    注释元素值或指定的值 使用等效的XML描述符 元素

  • 如果X是删除的实体, 它变得可以管理

  • 如果X是一个 分离对象 可能会引发EntityExistsException 调用persist操作时, 或
    实体存在异常
    或 另一个
    PersistenceException
    可能是 在刷新或提交时抛出

  • 为了 所有实体都由一个 来自X的关系,如果 与Y的关系已注释 使用级联元素值
    cascade=PERSIST
    cascade=ALL
    ,则 持久化操作应用于Y


合并操作的语义 适用于实体X的参数如下:

  • 如果X是分离的实体,则状态 将X的副本复制到预先存在的 同一实体的托管实体实例X' 标识或X的新托管副本X' 是创建的

  • 如果X是一个新实体 实例,一个新的托管实体 实例X'已创建,状态为 将X的副本复制到新的托管 实体实例X'

  • 如果X是一个 已删除实体实例,一个
    IllegalArgumentException
    将被删除 由合并操作(或 事务提交将失败)

  • 如果X 是托管实体,它被忽略 然而,在合并操作中 合并操作被级联到 关系引用的实体 从X开始,如果这些关系 已使用级联进行注释 元素值
    cascade=MERGE
    cascade=ALL
    注释

  • 总的来说 被关系引用的实体 从具有级联元素的X开始 值
    cascade=MERGE
    cascade=ALL
    ,Y 作为Y'递归合并。总的来说 这样的Y被X引用,X'被设置为 参考Y’。(注意,如果X是 那么托管X与 X')

  • 如果X是合并到X'的实体, 参考另一个实体Y, 其中
    cascade=MERGE
    cascade=ALL
    为 未指定,则为 X'的相同关联产生a 对托管对象Y'的引用,带有 与Y相同的持久标识


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

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

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


仅应在新实体上调用Persist,而
merge
用于重新连接分离的实体

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


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

最重要的区别在于:

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

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


javadoc非常明确地说明了它们的功能和区别。你读过并理解了吗?检查一下,谢谢你提供的信息。我看到了这两个定义的语义。但问题是它们之间的区别。对于
persist
merge
的每种不同行为,可能会列出状态列表和2个子部分。您能否在解释中添加一个来源?谢谢。@AlikElzin kilaka这样的解释,我记得,我在一本“JavaEE7入门”的书中找到过。