简体   繁体   English

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

[英]What is the difference between persist() and merge() in JPA and Hibernate?

What is the difference between persist() and merge() in Hibernate? Hibernate 中的persist() 和merge() 有什么区别?

persist() can create a UPDATE & INSERT query, eg: persist()可以创建一个 UPDATE & INSERT 查询,例如:

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
A a=new A();
session.persist(a);
a.setName("Mario");
session.flush();

in this case query will be generated like this:在这种情况下,查询将像这样生成:

Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?

so persist() method can generate an Insert and an Update.所以persist()方法可以生成一个插入和一个更新。

Now with merge() :现在使用merge()

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

This is what I see in the database:这是我在数据库中看到的:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti

Now update a record using merge()现在使用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();

This is what I see in the database:这是我在数据库中看到的:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley

JPA specification contains a very precise description of semantics of these operations, better than in javadoc: JPA 规范包含对这些操作语义的非常精确的描述,比 javadoc 中的要好:

The semantics of the persist operation, applied to an entity X are as follows:应用于实体 X 的持久操作的语义如下:

  • If X is a new entity, it becomes managed.如果 X 是一个新实体,它将成为托管。 The entity X will be entered into the database at or before transaction commit or as a result of the flush operation.实体 X 将在事务提交时或之前或作为刷新操作的结果输入到数据库中。

  • If X is a preexisting managed entity, it is ignored by the persist operation.如果 X 是预先存在的受管实体,则持久操作将忽略它。 However, the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities are annotated with the cascade=PERSIST or cascade=ALL annotation element value or specified with the equivalent XML descriptor element.但是,如果从 X 到这些其他实体的关系使用cascade=PERSISTcascade=ALL注释元素值注释或使用等效的 XML 描述符元素指定,则持久操作级联到由 X 引用的实体。

  • If X is a removed entity, it becomes managed.如果 X 是已删除的实体,则它变为托管的。

  • If X is a detached object, the EntityExistsException may be thrown when the persist operation is invoked, or the EntityExistsException or another PersistenceException may be thrown at flush or commit time.如果X是一个分离的目的, EntityExistsException当persist操作被调用时,或者可能抛出EntityExistsException或另一个PersistenceException可以在冲洗被抛出或提交时间。

  • For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value cascade=PERSIST or cascade=ALL , the persist operation is applied to Y.对于由来自 X 的关系引用的所有实体 Y,如果与 Y 的关系已使用级联元素值cascade=PERSISTcascade=ALL进行注释,则对 Y 应用持久操作。


The semantics of the merge operation applied to an entity X are as follows:应用于实体 X 的合并操作的语义如下:

  • If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X' of the same identity or a new managed copy X' of X is created.如果 X 是分离的实体,则 X 的状态被复制到具有相同身份的预先存在的受管实体实例 X' 上,或者创建 X 的新受管副本 X'。

  • If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.如果 X 是新的实体实例,则创建新的受管实体实例 X',并将 X 的状态复制到新的受管实体实例 X'。

  • If X is a removed entity instance, an IllegalArgumentException will be thrown by the merge operation (or the transaction commit will fail).如果 X 是已删除的实体实例,则合并操作将抛出IllegalArgumentException (否则事务提交将失败)。

  • If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships from X if these relationships have been annotated with the cascade element value cascade=MERGE or cascade=ALL annotation.如果 X 是受管实体,则合并操作将忽略它,但是,如果这些关系已使用级联元素值cascade=MERGEcascade=ALL注释,则合并操作级联到由来自 X 的关系引用的实体。

  • For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL , Y is merged recursively as Y'.对于由来自 X 的关系引用的所有实体 Y 具有级联元素值cascade=MERGEcascade=ALL ,Y 被递归合并为 Y'。 For all such Y referenced by X, X' is set to reference Y'.对于 X 引用的所有此类 Y,X' 设置为引用 Y'。 (Note that if X is managed then X is the same object as X'.) (请注意,如果 X 是被管理的,那么 X 与 X' 是同一个对象。)

  • If X is an entity merged to X', with a reference to another entity Y, where cascade=MERGE or cascade=ALL is not specified, then navigation of the same association from X' yields a reference to a managed object Y' with the same persistent identity as Y.如果 X 是合并到 X' 的实体,并引用另一个实体 Y,其中未指定cascade=MERGEcascade=ALL ,则从 X' 导航相同关联会产生对托管对象 Y' 的引用与 Y 相同的持久身份。

This is coming from JPA .这是来自JPA In a very simple way:以一种非常简单的方式:

  • persist(entity) should be used with totally new entities, to add them to DB (if entity already exists in DB there will be EntityExistsException throw). persist(entity)应该与全新的实体一起使用,将它们添加到 DB(如果 DB 中已经存在实体,则会抛出 EntityExistsException)。

  • merge(entity) should be used, to put entity back to persistence context if the entity was detached and was changed.应该使用merge(entity) ,如果实体被分离并被更改,则将实体放回持久性上下文。

Persist should be called only on new entities, while merge is meant to reattach detached entities. Persist 应该只在新实体上调用,而merge意味着重新附加分离的实体。

If you're using the assigned generator, using merge instead of persist can cause a redundant SQL statement.如果您使用指定的生成器,使用merge而不是persist可能会导致冗余的 SQL 语句。

Also, calling merge for managed entities is also a mistake since managed entities are automatically managed by Hibernate, and their state is synchronized with the database record by the dirty checking mechanism upon flushing the Persistence Context.此外,为托管实体调用合并也是一个错误,因为托管实体由 Hibernate 自动管理,并且它们的状态在刷新持久性上下文时通过脏检查机制与数据库记录同步。

The most important difference is this:最重要的区别是:

  • In case of persist method, if the entity that is to be managed in the persistence context, already exists in persistence context, the new one is ignored.persist方法的情况下,如果要在持久化上下文中管理的实体已经存在于持久化上下文中,则忽略新的实体。 (NOTHING happened) (什么都没有发生)

  • But in case of merge method, the entity that is already managed in persistence context will be replaced by the new entity (updated) and a copy of this updated entity will return back.但是在merge方法的情况下,已经在持久化上下文中管理的实体将被新实体(更新)替换,并且这个更新实体的副本将返回。 (from now on any changes should be made on this returned entity if you want to reflect your changes in persistence context) (从现在开始,如果您想在持久性上下文中反映您的更改,则应对此返回的实体进行任何更改)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM