我正在使用JPA + spring开发Web应用程序。我的项目层结构是web - >服务 - > DAO - > GenericDAO。所有类都被实例化为singleton spring bean。 GenericDAO使用@PersistenceContext注入entityManager实例。
我的应用程序在http会话中获取存储中的域实体。在对这些实体执行任何db操作之前,需要使用merge将其重新附加到实体管理器。我想知道将实体合并到实体管理器的最佳方法。目前每次调用事务方法时,我都调用genericDAO.merge(object)。 e.g。
@Transactional
public void addProducts() {
Order order = getOrderFromHttpSession();
genericDAO.merge(order);
// delete existing products
// add new products
// other db operations.
}
还有其他更好的方法吗?有没有可用的设计模式?
答案 0 :(得分:4)
我认为这是最好的方式。出于这个原因,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=MERGE
或cascade=ALL
注释- 对于来自X的关系引用的所有实体Y具有 级联元素值
cascade=MERGE
或cascade=ALL
,Y以递归方式合并 作为Y'。对于所有这样的Y引用 X,X'设置为引用Y'。 (注意 如果X被管理,那么X就是 与X'相同的对象。)- 如果X是合并到X'的实体,则引用另一个实体Y,其中
cascade=MERGE
或cascade=ALL
是。{ 未指定,然后导航 来自X'的相同关联产生a 引用托管对象Y' 与Y相同的持久性身份。持久性提供程序不能 合并标记为LAZY的字段没有 被抓取:它必须忽略这样 合并时的字段。
使用的任何
Version
列 必须通过实体检查实体 持久性运行时实现 在合并操作期间和/或在 刷新或提交时间。离席期间Version
列中没有 其他版本检查由 持久性提供程序运行时 合并期间。
另一种方法是em.find(someKey)并复制每个已更改的信息。 (但我不建议你这样做)。最佳实践是您的解决方案。