事务里 catch 了异常却还是报 Transaction silently rolled back because it has been marked as rollback-only?哪些写法会触发,哪些不会,表里到底剩什么?这篇用 H2 与 DataSourceTransactionManager 逐个复现。
[s1] outer 开着事务,调用 inner(REQUIRED)抛 RuntimeException,outer 把它 catch 掉后正常返回 → 抛出 UnexpectedRollbackException:Transaction rolled back because it has been marked as rollback-only;表 t 里的行:[]
在 catch 之后、方法返回之前,currentTransactionStatus().isRollbackOnly() = true
[s7] 同 s1,并在返回前打印 isRollbackOnly → 抛出 UnexpectedRollbackException:Transaction rolled back because it has been marked as rollback-only;表 t 里的行:[]内层标记共享事务回滚,外层吞掉异常却想提交。
[s2] inner 用 REQUIRES_NEW,抛 RuntimeException,outer catch 掉 → outer 正常返回;表 t 里的行:[outer] [s3] inner 用 noRollbackFor = IllegalStateException,抛 IllegalStateException,outer catch 掉 → outer 正常返回;表 t 里的行:[inner, outer] [s4] inner 就是 outer 自己的另一个方法(自调用,没有代理),抛 RuntimeException,outer catch 掉 → outer 正常返回;表 t 里的行:[inner, outer] [s5] inner 用 NESTED(保存点),抛 RuntimeException,outer catch 掉 → outer 正常返回;表 t 里的行:[outer] [s6] inner(REQUIRED)抛检查异常 Exception,outer catch 掉 → outer 正常返回;表 t 里的行:[inner, outer]
REQUIRES_NEW、NESTED、noRollbackFor、自调用、检查异常:outer 都能正常提交,表里结果各不相同。
[s8] outer 自己调用 setRollbackOnly() 后正常返回,没有任何 inner → outer 正常返回;表 t 里的行:[] [s9] outer 在 catch 里把 inner 的异常重新抛出 → 抛出 IllegalStateException:inner 失败;表 t 里的行:[]
setRollbackOnly 与重新抛出都不会抛 UnexpectedRollbackException。