Spring JpaRepository - 分离和附加实体 [英] Spring JpaRepository - Detach and Attach entity

查看:29
本文介绍了Spring JpaRepository - 分离和附加实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using spring boot and hibernate over jpa. I am using JpaRepository interface to implement my repositories. As with following UserRepository

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

我想实现以下

  1. 加载一个用户实体.
  2. 改变实体对象的状态,例如user.setName("foo")
  3. 执行外部系统网络服务调用.将调用结果保存在 DB 中
  4. 只有成功响应此网络服务调用,才会在存储库中保存用户的新状态.

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

All above steps are not happening in one transaction i.e. the external service call is out of transaction.

当我通过其存储库将我的 web 服务结果保存在数据库中时,我在用户实体中的更改也被保存.根据我的理解,这是由于第 3 步中底层持久性上下文的刷新.经过一些 google,我想我可以实现我的目的,如果我可以在第一步分离我的用户实体并在第 4 步重新附加它.请确认我的理解是否正确以及如何实现?JpaRepository 接口中没有分离实体的方法.

When I save my webservice result in DB via its repository, my changes in User entity are also saved. As per my understanding this is due to the flushing of underlaying persistence context at step # 3. After some google, I think I can achieve my purpose, if I can detach my user entity at step one and reattach it at step 4. Please confirm if my understanding is correct and how I can achieve this? There is not method in JpaRepository interface to detach an entity.

下面是代码来说明

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() 用于相同的目的.

If you are using JPA 2.0, you can use EntityManager#detach() to detach a single entity from persistence context. Also, Hibernate has a Session#evict() which serves the same purpose.

由于 JpaRepository 本身不提供此功能,您可以 给它添加一个自定义实现,像这样

Since JpaRepository doesn't provide this functionality itself, you can add a custom implementation to it, something like this

public interface UserRepositoryCustom {
    ...
   void detachUser(User u);
    ...
}

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

@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
    ...
    @PersistenceContext
    private EntityManager entityManager;

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

我没有试过这个代码,但你应该能够让它工作.您甚至可以尝试使用 @PersistenceContext 来控制您的服务类(updateUser() 所在的位置)中的 EntityManager,并避免麻烦将自定义实现添加到存储库.

I haven't tried this code, but you should be able to make it work. You might even try to get a hold on EntityManager in your service class (where updateUser() is) with @PersistenceContext, and avoid the hustle of adding custom implementation to repository.

这篇关于Spring JpaRepository - 分离和附加实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆