Spring事务回滚深度解析(面试高频考点)

▶ 最新面试资料下载:2025年Java面试宝典(提取码:9b3g)
二、Spring事务回滚的本质是什么?
Spring事务回滚的核心在于事务管理器(TransactionManager) 对数据库连接的管控。当我们用@Transactional注解声明方法时,Spring会在方法执行前开启事务,并将数据库连接绑定到当前线程。关键点在于:
- 方法正常结束时提交事务
- 方法抛出未捕获异常时触发回滚
面试官常问:“哪些异常会导致回滚?” 这里有个坑——默认只回滚RuntimeException和Error! 像SQLException这种受检异常是不会触发回滚的,必须通过@Transactional(rollbackFor=Exception.class)显式配置。
三、Spring事务回滚的4种触发场景
场景1:声明式事务的自动回滚
@Service
public class OrderService {
@Transactional // 默认回滚RuntimeException
public void createOrder() {
insertOrder(); // 步骤1
deductStock(); // 步骤2(抛出NullPointerException)
// 事务自动回滚
}
}
当deductStock()抛出运行时异常时,Spring会自动标记当前事务为rollback-only,最终由事务管理器执行回滚操作。
场景2:编程式回滚(精准控制)
@Autowired
private TransactionTemplate transactionTemplate;
public void updateData() {
transactionTemplate.execute(status -> {
try {
updateA();
updateB(); // 此处报错
} catch (BizException e) {
status.setRollbackOnly(); // 手动触发回滚
return "fail";
}
return "success";
});
}
通过TransactionCallback可以精确控制回滚节点,适用于复杂业务逻辑。
四、事务不回滚的3个经典坑点
坑点1:异常被捕获未抛出
@Transactional
public void process() {
try {
insertA(); // 抛出SQLException
} catch (Exception e) {
log.error("出错"); // 异常被吞掉,事务继续提交!
}
}
👉 解决方案:在catch中手动抛出new RuntimeException(e)
坑点2:跨方法调用失效
public class UserService {
public void register() {
saveUser(); // 调用内部方法
}
@Transactional // 注解失效!
private void saveUser() {
// 事务不会生效
}
}
👉 原理:Spring事务通过AOP代理实现,内部方法调用不走代理对象。
坑点3:多线程事务分离
@Transactional
public void multiThread() {
new Thread(() -> {
insertLog(); // 新线程不受主线程事务控制!
}).start();
}
👉 结论:事务绑定ThreadLocal,跨线程即失效。

五、高频面试题破解指南
-
Q:@Transactional(propagation=REQUIRES_NEW) 如何工作?
A:始终启动新事务,若已有事务则暂停(挂起)原事务。常用于日志记录等独立操作 -
Q:事务中先查数据再更新,可能出现什么问题?
A:脏读风险!默认隔离级别为READ_COMMITTED,需升级到REPEATABLE_READ或加版本锁 -
Q:SpringBoot如何配置多数据源事务?
A:需自定义ChainedTransactionManager,按顺序管理不同数据源事务(注意:非XA事务)
💡 面试备战提示:最近在整理Spring事务的深度题解时,发现面试鸭会员题库更新了大量2025年新题。通过面试鸭返利网下单可返利25元(官方直充无优惠),适合近期密集面试的同学。

▶ 本文关联资料:
返回首页 | 最新面试资讯


