Java Spring JpaRepository - 分离和附加实体
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26795436/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring JpaRepository - Detach and Attach entity
提问by amique
I am using spring boot and hibernate over jpa. I am using JpaRepository interface to implement my repositories. As with following UserRepository
我在 jpa 上使用 spring boot 和 hibernate。我正在使用 JpaRepository 接口来实现我的存储库。与以下 UserRepository 一样
public interface UserRepository extends JpaRepository<User, Long> {
}
I want to achieve following
我想实现以下目标
- Load a User entity.
- Change the state of entity object e.g. user.setName("foo")
- Do an external system webservice call. Save the call result in DB
- Only on successful response of this webservice call, save the new state of user in repository.
- 加载一个用户实体。
- 更改实体对象的状态,例如 user.setName("foo")
- 执行外部系统网络服务调用。将调用结果保存在数据库中
- 只有在成功响应此 webservice 调用后,才将用户的新状态保存在存储库中。
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.
当我通过其存储库将我的 Web 服务结果保存在 DB 中时,我在 User 实体中的更改也被保存。根据我的理解,这是由于第 3 步中底层持久性上下文的刷新。经过一些谷歌,我想我可以实现我的目的,如果我可以在第一步分离我的用户实体并在第 4 步重新附加它。请确认如果我的理解是正确的,我怎样才能做到这一点?JpaRepository 接口中没有分离实体的方法。
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
谢谢
采纳答案by Predrag Maric
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.
如果您使用的是 JPA 2.0,则可以使用EntityManager#detach()从持久化上下文中分离单个实体。此外,Hibernate 有一个用于相同目的的Session#evict()。
Since JpaRepository
doesn't provide this functionality itself, you can add a custom implementationto it, something like this
由于JpaRepository
本身不提供此功能,因此您可以向其添加自定义实现,如下所示
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.
我没有试过这段代码,但你应该能够让它工作。您甚至可以尝试使用 来控制EntityManager
您的服务类(在哪里updateUser()
)@PersistenceContext
,并避免将自定义实现添加到存储库的麻烦。
回答by Xstian
entityManager.clear()
will disconnect all the JPA objects, so that might not be an appropriate solution in all the cases, if you have other objects you do plan to keep connected.
entityManager.clear()
将断开所有 JPA 对象的连接,因此如果您确实计划保持连接其他对象,则这可能不是所有情况下的合适解决方案。
clear
清除
/**
* 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
entityManager.detach(entity);
从持久化上下文中删除给定的实体
detach
分离
/**
* 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);