Java事务回滚默认仅对RuntimeException及Error自动生效,受检异常需用rollbackFor显式指定;可编程调用setRollbackOnly()强制回滚;传播行为如REQUIRED或REQUIRES_NEW影响嵌套事务的回滚范围。

Java 中事务回滚主要通过异常触发自动回滚,或手动调用回滚方法实现。Spring 框架下最常用的是声明式事务(@Transactional),底层依赖于 AOP 和事务管理器(如 DataSourceTransactionManager)。是否回滚,关键看抛出的异常类型和事务配置。
默认回滚规则:运行时异常自动回滚
Spring 默认只对 未检查异常(RuntimeException 及其子类) 和 Error 执行回滚;对受检异常(如 Exception 或其子类,但非 RuntimeException)默认不回滚。
- 抛出
new RuntimeException("失败")→ 自动回滚 - 抛出
new IOException()→ 不回滚(除非显式配置) - 方法内捕获异常后“吞掉”,未重新抛出 → 不会触发回滚
显式指定回滚异常类型
使用 @Transactional(rollbackFor = {Exception.class}) 可让受检异常也触发回滚:
@Transactional(rollbackFor = {SQLException.class, IOException.class})
public void transferMoney() throws SQLException, IOException {
// 扣款、转账等操作
if (balance < amount) {
throw new SQLException("余额不足");
}
}
也可用 noRollbackFor 排除某些运行时异常不回滚(较少用)。
立即学习“Java免费学习笔记(深入)”;
编程式回滚:在代码中主动控制
当需要在特定逻辑分支中强制回滚(比如校验失败但不想抛异常),可注入 TransactionStatus 或使用 TransactionAspectSupport:
- 方式一:通过
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() - 方式二:在
PlatformTransactionManager管理的事务中调用status.setRollbackOnly()
示例:
@Transactional
public void processOrder(Order order) {
if (!inventoryService.hasStock(order.getItemId())) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
log.warn("库存不足,事务已标记为回滚");
return;
}
orderMapper.insert(order);
}
注意:setRollbackOnly() 不会立即终止方法执行,只是标记事务必须回滚;后续若再抛异常,仍按规则处理。
事务传播行为影响回滚范围
多个 @Transactional 方法嵌套调用时,传播行为(如 REQUIRED、REQUIRES_NEW)决定是否共用同一事务,进而影响回滚粒度:
-
REQUIRED(默认):加入外层事务,外层回滚则内层也回滚 -
REQUIRES_NEW:挂起外层事务,开启新事务;内层回滚不影响外层 - 若内层抛异常且未被捕获,外层未处理 → 外层事务也会因异常传播而回滚
因此,合理设计传播行为和异常处理边界,是精准控制回滚的关键。


















