rollbackOnly 是 Spring 框架在处理事务时的一个内部状态标记,表示当前事务已被标记为“仅回滚”(rollback-only)。一旦事务被设置为 rollbackOnly,即使后续没有显式抛出异常,Spring 也会在事务提交阶段强制回滚该事务。
为什么会触发 rollbackOnly?
- 在一个事务方法中调用了另一个带有
@Transactional注解的方法,且传播行为为REQUIRES_NEW或NESTED,而被调用方法抛出了未被捕获的异常。 - 手动调用
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。 - 数据库操作违反约束(如唯一索引冲突)导致底层 JDBC 回滚,Spring 捕获后将事务标记为 rollbackOnly。
常见错误场景
例如,在 Service A 中调用 Service B,两者都使用默认事务传播行为(REQUIRED)。若 Service B 抛出异常但被 Service A 捕获并吞掉,Spring 仍会将整个事务标记为 rollbackOnly,最终导致外层事务提交失败,并抛出类似以下异常:
org.springframework.transaction.UnexpectedRollbackException:
Transaction rolled back because it has been marked as rollback-only
如何解决?
- 避免吞掉异常,让异常正常传播。
- 合理使用事务传播行为,如对可能失败的子操作使用
REQUIRES_NEW隔离事务。 - 在必要时手动控制回滚逻辑,而非依赖默认行为。
理解 rollbackOnly 有助于更精准地控制 Spring 事务行为,避免因隐式回滚导致业务逻辑异常。