【发布时间】:2011-03-15 19:38:47
【问题描述】:
我在spring的事务管理中有以下奇怪的场景:
我有方法 A 调用方法 B 调用方法 C,它们每个都在不同的类中。方法 B 和 C 都包含事务。两者都使用 PROPAGATION_REQUIRED,因此当 spring 创建两个逻辑事务时,db 中有一个物理事务。
现在,在方法 C 中,我抛出了一个 RuntimeException。这将内部逻辑事务设置为 rollbackOnly 和物理事务。在方法 B 中,我知道 UnexpectedRollbackException 的可能性,所以我没有继续正常提交。我从 C 中捕获异常,然后抛出另一个 RuntimeException。
我希望外部 RuntimeException 会导致回滚到外部事务,但是实际行为是这样的:
- 外部事务似乎尝试提交,或至少检查其状态,然后它抛出 UnexpectedRollbackException,因为物理事务已被标记为 rollbackOnly。
- 在抛出该异常之前,它会在日志中打印另一个异常,指出“应用程序异常被提交异常覆盖”。因此,调用者 A 收到 UnexpectedRollbackException,而不是 B 抛出的异常。
我找到了一个解决方法,就是在抛出异常之前主动将外部事务设置为回滚
public ModelAndView methodB(HttpServletRequest req, HttpServletResponse resp) {
try{
other.methodC();
} catch (RuntimeException e){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new RuntimeException ("outer exception");
}
return handleGetRequest(req, resp);
}
但是,这种解决方法将代码与事务 api 紧密结合在一起,我想避免这种情况。有什么建议吗?
附言 这两个事务都是为了回滚运行时异常。我没有定义任何 rollbackFor 异常或类似的东西
【问题讨论】:
标签: java spring transactions