我正在使用spring boot并在jpa上休眠。我正在使用JpaRepository接口来实现我的存储库。与以下UserRepository一样
public interface UserRepository extends JpaRepository<User, Long> {
}
我想实现以下
上述所有步骤都不会发生在一个事务中,即外部服务调用不在事务中。
当我通过其存储库将我的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
}
由于
答案 0 :(得分:43)
如果您使用的是JPA 2.0,则可以使用EntityManager#detach()从持久性上下文中分离单个实体。此外,Hibernate有一个Session#evict(),它有同样的目的。
由于JpaRepository
本身并不提供此功能,您可add a custom implementation向它提供此类内容
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);
}
...
}
我还没有尝试过这段代码,但你应该能够让它运行起来。您甚至可以尝试使用EntityManager
来保留服务类(updateUser()
所在地)@PersistenceContext
,并避免将自定义实现添加到存储库。
答案 1 :(得分:4)
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);
答案 2 :(得分:0)
按照@Predrag Maric 的建议使用自定义实现显然是这个问题的正确答案。但是,我发现在服务层执行分离要好得多,因为它通常知道实体是否应该分离。
只需将其与服务中的 @PersistenceContext
连接即可。
@Service
class ConsumerServiceImpl {
@PersistenceContext
private EntityManager entityManager
...
entityManager.detach(en)