将分离的实体合并到 JPA 中的实体管理器的最佳方法是啥

Posted

技术标签:

【中文标题】将分离的实体合并到 JPA 中的实体管理器的最佳方法是啥【英文标题】:What is best way to merge detached entities to entity manager in JPA将分离的实体合并到 JPA 中的实体管理器的最佳方法是什么 【发布时间】:2014-11-24 12:33:30 【问题描述】:

我正在使用 JPA + spring 开发 Web 应用程序。我的项目层结构是web --> service --> DAO--> GenericDAO。所有类都被实例化为单例 spring bean。 GenericDAO 正在使用 @PersistenceContext 注入 entityManager 的实例。

我的应用程序在 http 会话中获取存储中的域实体。在我对这些实体执行任何数据库操作之前,需要使用合并将它重新附加到实体管理器。我想知道将实体合并到实体管理器的最佳方式。目前,每次调用事务方法时,我都会调用 genericDAO.merge(object)。 例如

@Transactional
public void addProducts() 
   Order order = getOrderFromHttpSession();
   genericDAO.merge(order);
   // delete existing products
   // add new products
   // other db operations.

有没有其他更好的方法来做到这一点。任何设计模式都可用于此?

【问题讨论】:

【参考方案1】:

我认为这是最好的方法。出于这个原因,JPA 提供了这种方法。

    /**
     * Merge the state of the given entity into the
     * current persistence context.
     * @param entity  entity instance
     * @return the managed instance that the state was merged to
     * @throws IllegalArgumentException if instance is not an
     *         entity or is a removed entity
     * @throws TransactionRequiredException if invoked on a
     *         container-managed entity manager of type
     *         <code>PersistenceContextType.TRANSACTION</code> and there is
     *         no transaction
     */
    public <T> T merge(T entity);

3.2.4.1 合并分离实体状态

合并操作允许 从分离状态传播 实体到持久实体 由 EntityManager 管理。

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

如果 X 是分离的实体,则 X 的状态将复制到预先存在的 相同的托管实体实例 X' 身份或 X 的新托管副本 X' 已创建。 如果 X 是一个新的实体实例,则创建一个新的托管实体实例 X' X 的状态被复制到 新的托管实体实例 X'。 如果 X 是已删除的实体实例,则 IllegalArgumentException 将是 由合并操作(或 事务提交将失败)。 如果 X 是一个托管实体,它会被合并操作忽略, 但是,合并操作是 级联到引用的实体 来自 X 的关系,如果这些 关系已用 级联元素值 cascade=MERGEcascade=ALL 注释。 对于由来自 X 的关系引用的所有实体 Y,具有 级联元素值cascade=MERGEcascade=ALL,Y递归合并 作为 Y'。对于所有这样的 Y 引用 X, X' 设置为参考 Y'。 (笔记 如果 X 是托管的,那么 X 是 与 X' 相同的对象。) 如果 X 是合并到 X' 的实体,并引用另一个实体 Y,其中 cascade=MERGEcascade=ALL 是 未指定,则导航 来自 X' 的相同关联产生 对托管对象 Y' 的引用 与 Y 相同的永久身份。

持久性提供者不得 合并标记为 LAZY 的字段 已获取:它必须忽略此类 合并时的字段。

任何Version 使用的列 实体必须由 持久性运行时实现 在合并操作期间和/或在 刷新或提交时间。离席期间 Version 列中没有 额外的版本检查由 持久性提供程序运行时 在合并操作期间。

另一种方法是 em.find(someKey) 并复制每个更改的信息。 (但我不建议你这样)。最佳做法是您的解决方案。

【讨论】:

感谢您对 merege 的详细解释。从性能的角度来看,每次使​​用合并是否会对性能产生影响?此外,我正在考虑编写自己的注释来扩展@transactional,并且在调用任何带有注释的方法时应该调用一个方法,并且我将合并到该方法中,这样每个开发人员都不需要编写合并。这会是一个好的设计并且在技术上是可行的吗? 取决于场景,但性能可以忽略不计,你记得那总是一个 ORM。对于您的第二个问题,您可以使用像 Orika 或 Dozer 这样执行深层复制的 bean 映射器,但还有很多其他的。无论如何,很高兴为您提供帮助:)

以上是关于将分离的实体合并到 JPA 中的实体管理器的最佳方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

分离实体和被管理实体

入门 jpa--实体管理器的基本应用

合并后未调用的分离实体的生命周期回调

删除分离实体spring jpa Repository接口

附加实体是否必须在JPA中合并?

合并有时在 JPA Hibernate 中失败,但在同一事务中 PERSIST 有效