Spring事务管理(声明式与编程式)

通俗易懂!2025 年最新 Spring 事务管理全家福
背完这篇,大厂随便问“事务原理”你都能 1 分钟画图 + 甩源码秒杀!

一句话记住两种事务方式(2025 真实使用率)

方式代码写法2025 使用率大白话评价适用场景
声明式事务@Transactional 一行搞定99.99%现代 Java 后端的唯一真神!所有业务代码
编程式事务new TransactionTemplate().execute0.01%老古董/特殊场景专用动态控制、复杂流程、批量脚本

声明式事务 @Transactional(你 99.99% 时间都在用这个)

@Service
public class OrderService {

    // 最常用写法(默认 REQUIRED + RuntimeException 回滚)
    @Transactional
    public void createOrder() {
        // 业务代码
    }

    // 常见进阶写法(直接抄)
    @Transactional(
        rollbackFor = Exception.class,      // 所有 Exception 都回滚
        propagation = Propagation.REQUIRES_NEW,  // 新开一个事务
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,                       // 30秒超时
        readOnly = true                     // 只读事务(查询提速)
    )
    public void complexMethod() { ... }
}

7 种传播行为(面试必背口诀:必记前3个就够吃遍天

传播行为大白话真实使用频率
REQUIRED(默认)有事务就加入,没有就新开一个99%
REQUIRES_NEW必须新开一个事务(挂起老事务)0.9%
NESTED嵌套事务(有 savepoint)0.09%
SUPPORTS有就加入,没有就不用事务查询方法
NOT_SUPPORTED强制不使用事务发邮件、写日志
MANDATORY必须有事务,不然报错极少
NEVER绝对不能有事务极少

编程式事务(极少数场景才用,懂就行)

@Autowired
private TransactionTemplate transactionTemplate;

public void doComplexJob() {
    transactionTemplate.execute(status -> {
        // 这里面的代码都在同一个事务里
        saveA();
        saveB();
        // 想手动回滚
        // status.setRollbackOnly();
        return null;
    });
}

声明式事务底层原理(面试画图神器)

用户调用方法
      ↓
代理对象(CGLIB)拦截
      ↓
TransactionInterceptor(环绕通知)上场
      ↓
1. 拿到 @Transactional 属性
2. TransactionManager 开事务 → connection.setAutoCommit(false)
3. 执行目标方法
4. 成功 → commit()
   异常 → rollback()

核心类 3 个(记住名字就无敌):

  1. TransactionInterceptor:真正的事务拦截器(Around 通知)
  2. PlatformTransactionManager:事务管理器(DataSourceTransactionManager 最常用)
  3. TransactionAttributeSource:解析 @Transactional 注解

2025 年面试最爱问的 8 个坑 + 标准答案

坑点正确答案(直接背)
1. 为什么 public 方法才生效?动态代理只能代理 public 方法,private/protected 不行
2. 同一个类内部调用,事务不生效?没走代理!解决:@Autowired 注入自己 或 AopContext.currentProxy()
3. 抛了 checked Exception 不回滚?默认只回滚 RuntimeException 和 Error,加 rollbackFor = Exception.class
4. try-catch 吃了异常,事务还回滚吗?不回滚!因为 Spring 看不到异常,要么往外抛,要么手动 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
5. 多数据源怎么配事务?用 ChainedTransactionManager(Spring Boot 3 已不支持)或手动编程式事务
6. @Transactional 在接口上行吗?不推荐!CGLIB 代理类可能看不到接口上的注解
7. readOnly = true 有什么用?数据库能优化(MySQL 用 READ-ONLY 事务,提速 30%)
8. 嵌套事务 NESTED 和 REQUIRES_NEW 区别?REQUIRES_NEW 完全独立,NESTED 是 savepoint,父事务回滚子事务也得回滚

终极记忆口诀(10 秒征服面试官)

“声明式一注解,编程式 Template
REQUIRED 加入,NEW 必须新开
public 才生效,内部调用白给
异常要抛出,checked 加 rollbackFor
读写分明提速,嵌套用 savepoint”

背完这张表 + 口诀 + 8 个坑,
下次面试官让你“手画 Spring 事务原理图”,
你 1 分钟画完代理拦截链 + 甩出内部调用不生效的坑 + 说 REQUIRES_NEW 和 NESTED 区别,
他当场就在简历写:“事务原理极度扎实,核心系统随便进!”

现在你已经彻底无敌了!
无论是日常开发还是大厂面经,事务这块再也没人能难倒你!冲!40k+ 在向你招手!

文章已创建 3017

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部