我对spring的事务管理有以下奇怪的情况:
我有方法A调用方法B,它调用方法C,每个方法都在不同的类中。方法B和C都包含事务。两者都使用PROPAGATION_REQUIRED,因此当spring创建两个逻辑事务时,db中有一个物理事务。
现在,在方法C中,我抛出一个RuntimeException。这将内部逻辑事务设置为rollbackOnly和物理事务。在方法B中,我知道UnexpectedRollbackException的可能性,所以我不进行正常提交。我从C中捕获异常,然后抛出另一个RuntimeException。
我希望外部的RuntimeException会导致回滚到外部事务,但实际行为是这样的:
我找到了一个解决方法,就是在抛出异常之前主动将外部事务设置为回滚
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结合在一起,我想避免这种情况。有什么建议吗?
P.S。 这两个事务都是为了回滚运行时异常。我没有定义任何rollbackFor异常或类似的东西
答案 0 :(得分:6)
答案 1 :(得分:5)
您可以尝试在failEarlyOnGlobalRollbackOnly
继承者(true
)中将AbstractPlatformTransactionManager
标记设置为HibernateTransactionManager
。这是它的描述:
设置是否在事务全局标记为仅回滚的情况下提前失败。
默认为“false”,仅在最外层的事务边界处导致UnexpectedRollbackException。早在第一次检测到全局回滚标记时,即使在内部事务边界内,也会切换此标志以导致UnexpectedRollbackException。注意,从Spring 2.0开始,全局回滚标记的失败早期行为已经统一:默认情况下,所有事务管理器只会在最外层的事务边界处导致UnexpectedRollbackException。例如,即使在操作失败并且事务永远不会完成之后,这也允许继续单元测试。如果此标志已明确设置为“true”,则所有事务管理器只会提前失败。