正确的 Hibernate 嵌套事务处理
Proper Hibernate nested transactions handling
我确定我遗漏了什么,但我不知道到底是什么...
给出以下片段:
@Service
public class MyClass {
private MyClass self;
private UserRepository userRepository;
private ApplicationContext applicationContext;
@PostConstruct
private void init() {
self = applicationContext.getBean(MyClass.class);
}
@Transactional
public void doA(User user) {
...
if (condition) {
self.doB(user);
throw new SecurityException();
}
user.setRandomField("x");
userRepository.save(user);
}
@Transactional(value = Transactional.TxType.REQUIRES_NEW)
public void doB(User user) {
...
userRepository.save(user);
}
}
我对 @Transactional
的了解是,如果使用它,调用 repository.save(entity)
是多余的。
我正在尝试做的是从事务方法处理实体,如果存在中断条件,则调用一个新方法(用 REQUIRES_NEW
注释),该方法将更新实体的某些字段实体并保存。然后根方法 (doA
) 抛出异常。仅供参考:在这种情况下 @Transactional(dontRollbackOn = SecurityException.class)
不是一个选项。
为了使用这种提交机制,我只是将当前的 bean 注入到一个名为 self
的变量中,而不是仅使用一种方法创建新的 bean,因此我可以使用 bean 代理进行事务管理。
奇怪的是,如果我从 doB
中删除 save
调用,当 doA
事务因 SecurityException
而回滚时,由doB
也被回滚。但如果我让它在那里,它会按预期工作。
我是做错了什么还是遗漏了什么?
谢谢!
尽量不要在 doB() 中传递 User 实例。
而是传递一个 Id 并在内部从回购中读取用户。我不确定在不同会话之间如何处理附加实体。
我确定我遗漏了什么,但我不知道到底是什么...
给出以下片段:
@Service
public class MyClass {
private MyClass self;
private UserRepository userRepository;
private ApplicationContext applicationContext;
@PostConstruct
private void init() {
self = applicationContext.getBean(MyClass.class);
}
@Transactional
public void doA(User user) {
...
if (condition) {
self.doB(user);
throw new SecurityException();
}
user.setRandomField("x");
userRepository.save(user);
}
@Transactional(value = Transactional.TxType.REQUIRES_NEW)
public void doB(User user) {
...
userRepository.save(user);
}
}
我对 @Transactional
的了解是,如果使用它,调用 repository.save(entity)
是多余的。
我正在尝试做的是从事务方法处理实体,如果存在中断条件,则调用一个新方法(用 REQUIRES_NEW
注释),该方法将更新实体的某些字段实体并保存。然后根方法 (doA
) 抛出异常。仅供参考:在这种情况下 @Transactional(dontRollbackOn = SecurityException.class)
不是一个选项。
为了使用这种提交机制,我只是将当前的 bean 注入到一个名为 self
的变量中,而不是仅使用一种方法创建新的 bean,因此我可以使用 bean 代理进行事务管理。
奇怪的是,如果我从 doB
中删除 save
调用,当 doA
事务因 SecurityException
而回滚时,由doB
也被回滚。但如果我让它在那里,它会按预期工作。
我是做错了什么还是遗漏了什么?
谢谢!
尽量不要在 doB() 中传递 User 实例。 而是传递一个 Id 并在内部从回购中读取用户。我不确定在不同会话之间如何处理附加实体。