Spring JpaRepository - 分离和连接实体 [英] Spring JpaRepository - Detach and Attach entity

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

问题描述

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

  public interface UserRepository扩展JpaRepository< User,Long> {
}

我想实现以下功能:


  1. 加载用户实体。

  2. 更改实体对象的状态,例如user.setName(foo)

  3. 执行外部系统web服务调用。将调用结果保存在数据库中

  4. 只有在成功响应此webservice调用后,才能将新用户的状态保存到存储库中。

以上所有步骤都不会在一次交易中发生,即外部服务呼叫不在交易中。

当我通过存储库将我的webservice结果保存在数据库中时,我的用户实体更改也被保存。根据我的理解,这是由于底部持久性上下文在第3步冲洗。在google之后,我认为我可以实现我的目的,如果我可以在步骤1分离我的用户实体并在步骤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); //这个调用还保存了步骤2中的更改

code
$ p
$ b

谢谢

解决方案

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

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

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

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

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

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

我还没有试过这段代码,但你应该能够使它工作。你甚至可以尝试在你的服务类中使用 EntityManager (其中 updateUser())) c $ c> @PersistenceContext ,并避免将自定义实现添加到存储库中。


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> {
}

I want to achieve following

  1. Load a User entity.
  2. Change the state of entity object e.g. user.setName("foo")
  3. Do an external system webservice call. Save the call result in DB
  4. Only on successful response of this webservice call, save the new state of user in repository.

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

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.

Following is the code to illustrate

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
}

Thanks

解决方案

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.

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

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天全站免登陆