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
答案 0 :(得分:142)
JPA specification包含对这些操作的语义的非常精确的描述,比javadoc更好:
持久性的语义 操作,应用于实体X 如下:
如果X是新实体,那么 变得有管理。实体X将是 在或之前进入数据库 事务提交或由于 冲洗操作。
如果X是a 预先存在的管理实体,它是 被持久化操作忽略。 但是,持续的操作是 级联到X引用的实体, 如果从X到这些的关系 其他实体用。注释
cascade=PERSIST
或cascade=ALL
注释元素值或指定 使用等效的XML描述符 元件。如果X是已移除的实体, 它变得有管理。
如果X是a 分离的对象, 可能会抛出
EntityExistsException
当调用持久化操作时, 或EntityExistsException
或 另一个PersistenceException
可能是 在刷新或提交时抛出。有关 a引用的所有实体Y. 来自X的关系,如果是 与Y的关系已被注释 具有级联元素值
cascade=PERSIST
或cascade=ALL
,{。}} 持久操作适用于Y。
合并操作的语义 应用于实体X如下:
如果X是分离的实体,则为状态 将X复制到预先存在的 管理实体实例X'相同 X的身份或新的托管副本X' 已创建。
如果X是新实体 例如,一个新的管理实体 实例X'创建和状态 将X复制到新的托管中 实体实例X'。
如果X是a 删除实体实例,
IllegalArgumentException
将是。{ 由合并操作抛出(或者 事务提交将失败)。如果是X. 是一个托管实体,它被忽略 然而,合并操作 合并操作级联到 关系引用的实体 来自X,如果这些关系有 已经注册了级联 元素值
cascade=MERGE
或cascade=ALL
注释。对所有人来说 关系引用的实体Y. 来自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相同的持久性身份。
答案 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 mechanism在flushing the Persistence Context上状态与数据库记录同步。
答案 3 :(得分:1)
最重要的区别是: 在persist方法的情况下,如果要在持久性上下文中管理的实体已经存在于持久性上下文中,则将忽略新的实体。 (没啥事儿) 但是在采用合并方法的情况下,已经在持久性上下文中管理的实体将被新实体替换(更新),并且此更新实体的副本将返回。 (从现在开始,如果您想在持久性上下文中反映您的更改,则应该对此返回的实体进行任何更改)