Spring JpaRepository – 分离和附加实体

我正在使用spring boot并在jpa上hibernate。 我正在使用JpaRepository接口来实现我的存储库。 与以下UserRepository一样

public interface UserRepository extends JpaRepository { } 

我想实现以下目标

  1. 加载用户实体。
  2. 更改实体对象的状态,例如user.setName(“foo”)
  3. 进行外部系统Web服务调用。 将呼叫结果保存在DB中
  4. 仅在成功响应此Web服务调用时,将新用户状态保存在存储库中。

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

当我通过其存储库将我的web服务结果保存在DB中时,我的用户实体更改也会保存。 根据我的理解,这是由于在步骤#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 } 

谢谢

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

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

 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); } ... } 

我没有尝试过这段代码,但你应该能够使它运行起来。 您甚至可以尝试使用@PersistenceContext在服务类(其中updateUser()是)中保留EntityManager ,并避免将自定义实现添加到存储库的喧嚣。

entityManager.clear()将断开所有JPA对象的连接,因此在所有情况下这可能不是一个合适的解决方案,如果您有其他对象计划保持连接。

明确

 /** * Clear the persistence context, causing all managed * entities to become detached. Changes made to entities that * have not been flushed to the database will not be * persisted. */ public void clear(); 

entityManager.detach(entity); 从持久性上下文中删除给定的实体

分离

 /** * Remove the given entity from the persistence context, causing * a managed entity to become detached. Unflushed changes made * to the entity if any (including removal of the entity), * will not be synchronized to the database. Entities which * previously referenced the detached entity will continue to * reference it. * @param entity entity instance * @throws IllegalArgumentException if the instance is not an * entity * @since Java Persistence 2.0 */ public void detach(Object entity);