@Transactional 嵌套,内层抛异常,外层用 try-catch 捕获但实际事务却回滚了
1. 内层事务传播行为为 Propagation.REQUIRED
且设置了回滚标记
虽然外层捕获了异常,但内层事务在抛出异常时可能已经标记了整个事务需要回滚。在 Spring 中,当内层事务传播行为为 Propagation.REQUIRED
时,它和外层事务属于同一个逻辑事务。若内层在抛出异常前或者异常处理逻辑中调用了 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
方法,那么即使外层捕获了异常,事务也会回滚。
2. 数据库隔离级别和锁机制影响
某些数据库的隔离级别和锁机制可能会导致即使异常被捕获,事务也会回滚。例如,在一些高并发场景下,当内层事务持有锁,并且在异常发生时数据库为了保证数据一致性,强制回滚整个事务。这种情况通常与数据库的具体实现和配置有关。
3. 异常类型与 rollbackFor
配置
如果 @Transactional
注解中配置了 rollbackFor
属性,并且内层抛出的异常类型符合该配置,即使外层捕获了异常,Spring 可能仍然会根据配置决定回滚事务。
4. AOP 代理问题
Spring 的事务管理是基于 AOP 代理实现的。如果代码存在 AOP 代理相关的问题,例如代理配置错误、方法调用不符合 AOP 代理规则等,可能会导致事务行为不符合预期。比如,在同一个类中,非代理方法调用带有 @Transactional
注解的方法,可能会绕过事务代理逻辑,导致事务行为异常。