Jpa中的persist方法和merge方法都有哪些区别,帮我举一个例子解释下?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jpa中的persist方法和merge方法都有哪些区别,帮我举一个例子解释下?相关的知识,希望对你有一定的参考价值。

1、含义不同

persist是保存,跟save方法一样,更接近持久化的含义;而merge是合并的意思,就是当保存的实体,根据主键id划分,如果已存在,那么就是更新操作,如果不存在,就是新增操作。

2、用法不同

persist会把传进去的实体放到持久化上下文中,此时如果持久化上下文中有了这个实体,就会抛出javax.persistence.EntityExistsException,没有的话事务提交的时候把那个对象加进数据库中。

而merge会在持久化上下文中生成传进去的实体的受管版本,如果已经有了受管版本,那也不会抛出异常,然后把那个受管的实体返回出来,事务提交的时候如果数据库中不存在那个对象(那一行),就把把那个受管的加进去,存在的话就替换掉原来的数据。

扩展资料:

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。

JPA定义了独特的JPQL,JPQL是EJB
QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP
BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

参考资料来源:百度百科—JPA

参考技术A persist(),是保存,跟save()方法一样,知识jpa官方说叫persist比较好一些,更接近持久化的含义。而merge()是合并的意思,就是当你保存的实体,根据主键id划分,如果已存在,那么就是更新操作,如果不存在,就是新增操作。

persist会把传进去的实体放到持久化上下文中,此时如果持久化上下文中有了这个实体,就会抛出javax.persistence.EntityExistsException,没有的话事务提交的时候把那个对象加进数据库中,如果数据库中已经存在了那个对象(那一行),就会抛出com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;

而merge会在持久化上下文中生成传进去的实体的受管版本,如果已经有了受管版本,那也不会抛出异常,然后把那个受管的实体返回出来,事务提交的时候如果数据库中不存在那个对象(那一行),就把把那个受管的加进去,存在的话就替换掉原来的数据。merge是如果持久化上下文中有了受管版本,那就更新,没有就复制一份,返回受管的。

再次总结persist(①,②-③,④-⑤):
(这里说的抛出的异常都是指对象(或者数据库中的行)重复的异常)
① 如果persist的是一个受管实体(即已经在上下文中),就不会抛出异常。
②如果persist的是一个游离实体(即上下文中没有它),而上下文中又没有它的受管版本,数据库中也没有,也不会抛出异常,而会把这个实体写进数据库中。
③如果persist的是一个游离实体(即上下文中没有),而上下文中又没有它的受管版本,数据库却有这个实体,那么EntityManager在persist它的时候不会抛出异常,但是事务提交的时候就会抛出异常:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '7' for key 1;
④如果persist的是一个游离实体(即上下文中没有),而上下文中却有它的受管版本,数据库中又没有这个实体,那么还是不会抛出异常,而是把它的受管版本加进去(不是那个游离的,是那个受管的!)(即,这种情况persist和没persist是一样的!)。
⑤如果persist的是一个游离实体(即上下文中没有),而上下文中却有它的受管版本,数据库中也有了这个实体,那么EntityManager在persist它的时候就会抛出异常:javax.persistence.EntityExistsException
而merge就不会抛出什么对象重复的异常的了。。
参考技术B persist(),是保存,跟save()方法一样,知识jpa官方说叫persist比较好一些,更接近持久化的含义。而merge()是合并的意思,就是当你保存的实体,根据主键id划分,如果已存在,那么就是更新操作,如果不存在,就是新增操作。 参考技术C persist(),是保存,跟save()方法一样,知识jpa官方说叫persist比较好一些,更接近持久化的含义。而merge()是合并的意思,就是当你保存的实体,根据主键id划分,如果已存在,那么就是更新操作,如果不存在,就是新增操作。 参考技术D persist(),是保存,跟save()方法一样,知识jpa官方说叫persist比较好一些,更接近持久化的含义。而merge()是合并的意思,就是当你保存的实体,根据主键id划分,如果已存在,那么就是更新操作,如果不存在,就是新增操作。

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

【中文标题】JPA 和 Hibernate 中的 persist() 和 merge() 有啥区别?【英文标题】:What is the difference between persist() and merge() in JPA and Hibernate?JPA 和 Hibernate 中的 persist() 和 merge() 有什么区别? 【发布时间】:2011-05-29 09:19:06 【问题描述】:

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() 方法可以生成插入和更新。

现在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

【问题讨论】:

javadoc 非常明确地说明了它们的作用以及它们之间的区别。你读过并理解了吗? 检查***.com/questions/161224/… ***.com/questions/1069992/… 【参考方案1】:

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

persist 的语义 操作,应用于实体 X 是 如下:

如果 X 是一个新实体,它 成为管理的。实体 X 将是 在或之前输入数据库 事务提交或由于 刷新操作。

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

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

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

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


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

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

如果 X 是一个新实体 实例,一个新的托管实体 实例 X' 被创建并且状态 的 X 被复制到新的托管 实体实例 X'。

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

如果 X 是一个托管实体,它被忽略 合并操作,然而, 合并操作被级联到 关系引用的实体 从 X 如果这些关系有 被级联注释 元素值cascade=MERGEcascade=ALL注解。

为所有人 关系引用的实体 Y 从具有级联元素的 X 值cascade=MERGEcascade=ALL, Y 递归地合并为 Y'。对所有人 X 引用的这样的 Y,X' 设置为 参考 Y'。 (注意,如果 X 是 托管然后 X 是相同的对象 X'。)

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

【讨论】:

感谢您的信息。我看到了这两个定义的语义。但问题是关于它们之间的差异。也许为persistmerge 的每个不同行为提供状态列表和2 个子部分?【参考方案2】:

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

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

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

【讨论】:

您能否在解释中添加来源?谢谢。 @AlikElzin-kilaka 这样的解释,我记得,我在“Beginning Java EE 7”一书中找到了。【参考方案3】:

仅应在新实体上调用 Persist,而 merge 旨在重新附加分离的实体。

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

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

【讨论】:

【参考方案4】:

最重要的区别是:

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

但在merge 方法的情况下,已在持久性上下文中管理的实体将被新实体(更新)替换,并且此更新实体的副本将返回。 (从现在开始,如果您想在持久性上下文中反映您的更改,则应在此返回的实体上进行任何更改)

【讨论】:

以上是关于Jpa中的persist方法和merge方法都有哪些区别,帮我举一个例子解释下?的主要内容,如果未能解决你的问题,请参考以下文章

1.EntityManaget的persist和merge方法的区别

hibernate中的merge()方法

Hibernate中Session的save()update()merge()lock()saveOrUpdate()和persist()方法的区别

JPA核心类与使用

Hibernate Session的save()update()merge()lock()saveOrUpdate()和persist()方法分别是做什么的?有什么区别?

不在JPA 的 persistence.xml 文件里配置Entity class的解决的方法