我在 jpa 上使用 spring boot 和 hibernate。我正在使用 JpaRepository 接口来实现我的存储库。与以下 UserRepository 一样
public interface UserRepository extends JpaRepository<User, Long> {
}
我想实现以下目标
- 加载用户实体。
- 更改实体对象的状态,例如 user.setName(“foo”)
- 进行外部系统网络服务调用。将调用结果保存到数据库中
- 只有在成功响应此 web 服务调用后,才会将用户的新状态保存在存储库中。
以上所有步骤都不会在一个事务中发生,即外部服务调用不在事务中。
当我通过其存储库将我的 web 服务结果保存在数据库中时,我在用户实体中的更改也被保存。根据我的理解,这是由于在第 3 步刷新了底层持久性上下文。经过一些谷歌搜索,我认为我可以实现我的目的,如果我可以在第一步分离我的用户实体并在第 4 步重新附加它。请确认如果我的理解是正确的,我该如何实现? JpaRepository 接口中没有分离实体的方法。
下面是代码来说明
public void updateUser(int id, String name, int changeReqId){
User mUser = userRepository.findOne(id); //1
mUser.setName(name); //2
ChangeRequest cr = changeRequestRepository.findOne(changeReqId);
ChangeResponse rs = userWebService.updateDetails(mUser); //3
if(rs.isAccepted()){
userRepository.saveAndFlush(mUser); //4
}
cr.setResponseCode(rs.getCode());
changeRequestRepository.saveAndFlush(cr); //this call also saves the changes at step 2
}
谢谢
原文由 amique 发布,翻译遵循 CC BY-SA 4.0 许可协议
如果您使用的是 JPA 2.0,则可以使用 EntityManager#detach() 从持久性上下文中分离单个实体。此外,Hibernate 有一个 Session#evict() 用于相同的目的。
由于
JpaRepository
本身不提供此功能,您可以 向其添加自定义实现,如下所示我还没有尝试过这段代码,但你应该能够让它工作。您甚至可以尝试在您的服务类中保留
EntityManager
(其中updateUser()
是)和@PersistenceContext
,并避免将自定义实现添加到存储库 - a1 .