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

jav*_*fan 3 merge spring jpa entitymanager

我正在使用JPA + spring开发Web应用程序。我的项目层结构是Web->服务-> 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.
}
Run Code Online (Sandbox Code Playgroud)

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

Xst*_*ian 5

我认为这是最好的方法。为此,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);
Run Code Online (Sandbox Code Playgroud)

3.2.4.1合并独立实体状态

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

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

  • 如果X是一个分离的实体,则将X的状态复制到具有相同标识的预先存在的管理实体实例X'上,或者创建X的新的管理副本X'。
  • 如果X是新的实体实例,则创建新的管理实体实例X',并将X的状态复制到新的管理实体实例X'中。
  • 如果X是已删除的实体实例,IllegalArgumentException则合并操作将抛出an (否则事务提交将失败)。
  • 如果X是受管实体,则合并操作将忽略它,但是,如果已用级联元素值cascade=MERGEcascade=ALL 注释对这些关系进行了注释,则合并操作将级联到X的关系所引用的实体 。
  • 对于由来自具有级联元素值cascade=MERGE或的 X的关系引用的所有实体Y cascade=ALL,将Y递归合并为Y'。对于X引用的所有此类Y,将X'设置为引用Y'。(请注意,如果管理X,则X与X'是同一对象。)
  • 如果X是合并到X'的实体,并引用了另一个实体Y(其中 未指定cascade=MERGE或未cascade=ALL指定),则从X'导航相同的关联会生成对具有与Y相同的持久标识的托管对象Y'的引用。

持久性提供程序不得合并尚未提取的标记为LAZY的字段:合并时必须忽略此类字段。

Version持久性运行时实现必须在合并操作期间和/或在刷新或提交时检查实体使用的任何列。在没有Version列的情况下,持久性提供程序运行时在合并操作期间不会执行其他版本检查。

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