在 Spring 个数据存储库之上使用 EntityManager
Using EntityManager on top of Spring Data Repositories
最近,我遇到了以下代码:
@Transactional
public MyEntity insert(MyEntity entity) {
MyEntity merged = entityManager.merge(entity);
return myEntityRepository.save(merged);
}
其中实体管理器定义如下:
@PersistenceContext private EntityManager entityManager;
存储库是 Spring QueryDSL 存储库:
@Repository
public interface MyEntityRepository extends QueryDslRepository<MyEntity>{
}
我的问题是,当我们使用 myEntityRepository
持久化实体时,是否真的有必要调用 entityManager.merge(entity)
?是否有 entityManager 正在做的存储库不能做的事情?调用存储库还不够吗?
在我看来,这就像货物崇拜编程。 implementation of save()
已经在必要时进行了合并(有时在不需要时):
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
对我来说,这看起来是一个非常危险的代码,其意图有点模糊并且有些过度设计:
- 你能 100% 保证在你的层和存储库之间共享同一个事务管理器吗?否则你就有麻烦了。
- 你只是在做双重工作(@Jens 的回答表明了这一点)。
@Transactional
这里只会让事情变得更糟(如果你有一些非标准的刷新策略)。特别要注意,如果您从与通过代理工作的相同 class 中调用方法,它将无法工作。
- 如果你真的打算
insert()
(新记录)你为什么需要merge()
?
我的投票是——按照@Jens 指出的那样使用save()
。如果您确实需要 insert()
功能,那么您可能需要具有更新保护的真实事务,在这种情况下,我会在存储库层上做一些自定义代码。希望你不需要它。
最近,我遇到了以下代码:
@Transactional
public MyEntity insert(MyEntity entity) {
MyEntity merged = entityManager.merge(entity);
return myEntityRepository.save(merged);
}
其中实体管理器定义如下:
@PersistenceContext private EntityManager entityManager;
存储库是 Spring QueryDSL 存储库:
@Repository
public interface MyEntityRepository extends QueryDslRepository<MyEntity>{
}
我的问题是,当我们使用 myEntityRepository
持久化实体时,是否真的有必要调用 entityManager.merge(entity)
?是否有 entityManager 正在做的存储库不能做的事情?调用存储库还不够吗?
在我看来,这就像货物崇拜编程。 implementation of save()
已经在必要时进行了合并(有时在不需要时):
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
对我来说,这看起来是一个非常危险的代码,其意图有点模糊并且有些过度设计:
- 你能 100% 保证在你的层和存储库之间共享同一个事务管理器吗?否则你就有麻烦了。
- 你只是在做双重工作(@Jens 的回答表明了这一点)。
@Transactional
这里只会让事情变得更糟(如果你有一些非标准的刷新策略)。特别要注意,如果您从与通过代理工作的相同 class 中调用方法,它将无法工作。- 如果你真的打算
insert()
(新记录)你为什么需要merge()
?
我的投票是——按照@Jens 指出的那样使用save()
。如果您确实需要 insert()
功能,那么您可能需要具有更新保护的真实事务,在这种情况下,我会在存储库层上做一些自定义代码。希望你不需要它。