Spring @Transactional 注解从入门到避坑指南

 更新时间:2026年05月06日 10:43:35   作者:ffqws_  
文章主要讲解了Spring的@Transactional注解的使用场景、核心属性详解、事务传播行为、隔离级别、回滚配置、底层原理以及失效场景和避免之道,并还给出了最佳实践,感兴趣的朋友跟随小编一起看看吧

一、为什么需要事务?

想象一个下单场景:

  1. 创建订单
  2. 扣减库存
  3. 扣除用户余额

如果第2步成功了,第3步失败,库存已经扣了但钱没扣,数据就乱了。事务的作用就是保证这一组操作要么全成功,要么全失败。

二、快速使用

@Service
public class OrderService {
    @Transactional
    public void submitOrder(OrdersSubmitDTO dto) {
        orderMapper.insert(order);           // 插入订单
        orderDetailMapper.insertBatch(list); // 插入明细
        shoppingCartMapper.clean(userId);    // 清空购物车
    }
}

加了这个注解,方法内所有数据库操作会被包装在一个事务中。任意一步抛异常,Spring 会自动回滚。

三、核心属性详解

属性作用常用值
propagation事务传播行为REQUIRED(默认)、REQUIRES_NEW
isolation隔离级别READ_COMMITTEDREPEATABLE_READ
rollbackFor指定回滚的异常类型Exception.class
noRollbackFor指定不回滚的异常IllegalArgumentException.class
timeout事务超时时间(秒)-1(默认无限制)
readOnly是否为只读事务true / false

3.1 propagation 传播行为

@Transactional(propagation = Propagation.REQUIRED)  // 默认
public void methodA() {
    // 如果已有事务,加入;没有则新建
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // 挂起当前事务,新建一个独立事务
}

常见场景:日志记录必须保存,不管主业务是否回滚。此时日志方法用 REQUIRES_NEW,主业务回滚不影响日志。

3.2 isolation 隔离级别

@Transactional(isolation = Isolation.READ_COMMITTED)
隔离级别脏读不可重复读幻读
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE_READ
SERIALIZABLE

MySQL 默认 REPEATABLE_READ,Spring 默认跟随数据库。

3.3 rollbackFor 回滚配置

重点:默认只回滚 RuntimeException 和 Error

// 错误示范:IOException 不会触发回滚!
@Transactional
public void pay() throws IOException {
    // ...
}
// 正确配置:回滚所有异常
@Transactional(rollbackFor = Exception.class)
public void pay() throws IOException {
    // ...
}

四、底层原理(简述)

Spring 通过 AOP 动态代理 实现事务:

  1. 运行时生成目标类的代理对象
  2. 方法执行前开启事务(begin
  3. 方法正常结束则提交(commit
  4. 方法抛异常则回滚(rollback

这也是为什么同类内部调用会导致事务失效——绕过了代理对象。

五、失效场景全解析(避坑指南)

场景 1:同类内部调用(最高频)

@Service
public class OrderService {
    public void createOrder() {
        saveOrder(); // 直接调用,事务失效!
    }
    @Transactional
    public void saveOrder() {
        // ...
    }
}

原因this.saveOrder() 没有走代理对象。

解决

@Autowired
private OrderService orderService;
public void createOrder() {
    orderService.saveOrder(); // 通过注入的代理调用
}

场景 2:异常被吞掉

@Transactional
public void submit() {
    try {
        orderMapper.insert(order);
        payService.pay(); // 抛异常
    } catch (Exception e) {
        log.error("支付失败", e);
        // 异常没抛出去,Spring 认为成功,提交事务!
    }
}

解决

} catch (Exception e) {
    throw new RuntimeException(e);
    // 或者手动回滚:
    // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}

场景 3:异常类型不匹配

如 3.3 所述,受检异常(IOExceptionSQLException)默认不回滚。

场景 4:方法非 public

@Transactional 只能作用于 public 方法。

场景 5:数据库引擎不支持

MySQL 的 MyISAM 引擎不支持事务,表必须是 InnoDB

六、最佳实践

  1. 尽量放在 Service 层,不要在 Controller 或 Mapper 上加
  2. 事务方法尽量精简,避免长事务(大事务会锁表、拖垮性能)
  3. 查询操作加 readOnly = true
  4. 明确指定 rollbackFor = Exception.class,避免受检异常漏网
  5. 不要在事务里调外部 HTTP 接口,会拉长事务时间

七、总结

要点记忆口诀
代理调用才生效同类 this. 调用要警惕
异常必须抛出去别在 catch 里默默吞掉
回滚范围要明确rollbackFor = Exception.class
长事务是性能杀手查询加 readOnly,事务尽量短

到此这篇关于Spring @Transactional 注解详解:从入门到避坑的文章就介绍到这了,更多相关Spring @Transactional 注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解mybatis中association和collection的column传入多个参数问题

    详解mybatis中association和collection的column传入多个参数问题

    这篇文章主要介绍了详解mybatis中association和collection的column传入多个参数问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • Java实现简单QQ聊天工具

    Java实现简单QQ聊天工具

    这篇文章主要为大家详细介绍了Java实现简单QQ聊天工具,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • java多线程开发之通过对战游戏学习CyclicBarrier

    java多线程开发之通过对战游戏学习CyclicBarrier

    这篇文章给大家分享了关于java多线程开发中通过对战游戏学习CyclicBarrier的相关知识点内容,有兴趣的朋友们学习参考下。
    2018-08-08
  • Java 时间转换的实例代码

    Java 时间转换的实例代码

    下面小编就为大家带来一篇Java 时间转换的实例代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • logback 自定义Pattern模板教程

    logback 自定义Pattern模板教程

    这篇文章主要介绍了logback 自定义Pattern模板教程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java三级菜单工具类实现方式

    Java三级菜单工具类实现方式

    这篇文章通过实例代码给大家介绍Java三级菜单工具类实现方式,常用的三个字段,子级id、父级id、其次是数组children,本文结合实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2024-05-05
  • java异常与错误处理基本知识

    java异常与错误处理基本知识

    本文内容是java的异常与错误处理基本知识
    2013-11-11
  • Java中文乱码解决方案全解析,让你的程序“说人话”!

    Java中文乱码解决方案全解析,让你的程序“说人话”!

    探索Java中文乱码解决方案全解析,让你的程序终于能“说人话”!厌倦了看着一串串的问号或者奇怪符号吗?跟着我们的指南,一步步轻松解锁中文乱码的秘密,让你的代码清晰表达每一个字,需要的朋友可以参考下
    2024-02-02
  • SpringBoot实现健康检查的完整指南

    SpringBoot实现健康检查的完整指南

    本文介绍了Spring Boot实现健康检查的方法,包括使用Actuator进行应用健康检查,自定义健康检查项目,搭建可视化监控大屏和配置告警系统,此外,还提供了实战案例和避坑指南,帮助读者更好地理解和应用Spring Boot健康检查功能,需要的朋友可以参考下
    2025-12-12
  • 扩展tk.mybatis的流式查询功能实现

    扩展tk.mybatis的流式查询功能实现

    mybatis查询默认是一次获取全部,如果数据过于庞大,就会导致OOM问题,本文就介绍了tk.mybatis 流式查询,具有一定的参考价值,感兴趣的可以了解一下
    2021-12-12

最新评论