一尘不染

Spring JpaRepository-分离并附加实体

spring

我正在使用Spring Boot并通过jpahibernate。我正在使用JpaRepository接口来实现我的存储库。与以下UserRepository一样

public interface UserRepository extends JpaRepository<User, Long> {
}

我想实现以下目标

加载用户实体。

  1. 更改实体对象的状态,例如user.setName(“ foo”)
  2. 进行外部系统Web服务调用。将通话结果保存到数据库中
  3. 仅在成功响应此Web服务调用后,才将用户的新状态保存在存储库中。

以上所有步骤都不会在一个事务中发生,即外部服务调用已结束事务。

当我通过Web服务的存储库将Webservice结果保存在DB中时,我在User实体中的更改也被保存。根据我的理解,这是由于在步骤#3中清除了持久性上下文的原因。经过一番google之后,如果我可以在第一步中分离用户实体并在步骤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
}

谢谢


阅读 406

收藏
2020-04-18

共1个答案

一尘不染

如果使用的是JPA 2.0,则可以使用EntityManager#detach()从持久性上下文中分离单个实体。另外,Hibernate具有一个Session#evict(),它具有相同的作用。

由于JpaRepository本身不提供此功能,因此您可以向其添加自定义实现,如下所示

public interface UserRepositoryCustom {

void detachUser(User u);

}

public interface UserRepository extends JpaRepository, UserRepositoryCustom {

}

@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {

@PersistenceContext
private EntityManager entityManager;

@Override
public void detachUser(User u) {
    entityManager.detach(u);
}
...

}
我没有尝试过此代码,但是您应该可以使其工作。您甚至可以尝试通过保留EntityManager服务类(在哪里updateUser())@PersistenceContext,并避免将自定义实现添加到存储库的麻烦。

2020-04-18