@Transactional注解
2026/7/12 16:43:23 网站建设 项目流程

@Transactional注解

    • 一、 核心工作原理
    • 二、 关键属性详解
    • 三、 常见失效场景与避坑指南
    • 四、 总结建议

@Transactional是 Spring 框架中实现声明式事务管理的核心注解。它通过 AOP(面向切面编程)动态代理机制,将事务的开启、提交、回滚逻辑从业务代码中剥离,极大简化了开发。

一、 核心工作原理

Spring 在运行时为标注了@Transactional的 Bean 创建代理对象。

  • 方法调用前:代理对象拦截请求,根据配置获取或创建事务。
  • 方法执行中:执行业务逻辑。
  • 方法结束后:若无异常则提交事务;若抛出指定异常则回滚事务。

注意:默认情况下,Spring 仅对public方法生效,且自调用(类内部方法互调)会导致事务失效,因为绕过了代理对象。

二、 关键属性详解

  1. propagation(传播行为)
    决定当前方法被另一个事务方法调用时,事务如何传播。默认值为REQUIRED
传播行为含义场景示例
REQUIRED如果当前存在事务,则加入;否则新建一个。大多数业务场景,保证操作在同一事务中。
REQUIRES_NEW无论当前是否有事务,都新建一个独立事务。挂起当前事务。记录日志、审计信息,即使主事务回滚,日志也要保存。
NESTED如果当前存在事务,则在嵌套事务内执行(保存点机制);否则新建。部分成功部分失败的场景,内部回滚不影响外部。
SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。查询操作,有事务就用,没有也行。
NOT_SUPPORTED以非事务方式执行,如果当前存在事务,则挂起当前事务。高性能非 DB 操作。
MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。强制要求必须在事务环境中运行。
NEVER以非事务方式执行,如果当前存在事务,则抛出异常。严禁在事务中运行。
  1. isolation(隔离级别)
    指定事务的隔离级别,解决并发问题。默认值为数据库默认级别(如 MySQL 为READ_COMMITTEDREPEATABLE_READ,取决于配置)。
  • DEFAULT:使用底层数据库的默认隔离级别。
  • READ_UNCOMMITTED:读未提交。
  • READ_COMMITTED:读已提交。
  • REPEATABLE_READ:可重复读。
  • SERIALIZABLE:串行化。
  1. rollbackFor / noRollbackFor(回滚规则)
    决定哪些异常触发回滚。
  • 默认规则:只有RuntimeException(运行时异常)和Error会触发回滚,检查型异常(Checked Exception,如 IOException)不会回滚。
  • 最佳实践:通常设置rollbackFor = Exception.class,确保所有异常都回滚,避免数据不一致。
@Transactional(rollbackFor=Exception.class)publicvoidupdateData(){...}
  1. timeout(超时时间)
    事务运行的最大秒数。超过该时间未提交,自动回滚。防止长事务占用数据库连接资源。
@Transactional(timeout=30)// 30秒超时
  1. readOnly(只读优化)
    提示数据库和 Hibernate 该事务只进行读取操作。
  • 作用:Hibernate 可以跳过脏检查,数据库可能优化查询计划。
  • 注意:如果在只读事务中执行写操作,通常会抛出异常。
@Transactional(readOnly=true)publicList<User>findAll(){...}

三、 常见失效场景与避坑指南

  1. 自调用失效

    • 现象:类 A 的方法 a() 调用同类的方法 b(),b() 上有@Transactional,但事务不生效。
    • 原因:Spring 事务基于代理,自调用直接访问目标对象,绕过了代理类的事务增强逻辑。
    • 解决:
      • 注入自身 Bean 调用。
      • 使用AopContext.currentProxy()获取代理对象调用。
      • 将方法拆分到不同的 Service 类中。
  2. 异常被吞没

    • 现象:方法内部try-catch捕获了异常但未抛出,事务不回滚。
    • 原因:Spring 只有在异常抛出到代理层时才能感知并回滚。
    • 解决:在 catch 块中手动抛出RuntimeException,或调用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
  3. 方法非 public

    • 现象:注解在privateprotected或默认权限方法上。
    • 原因:Spring 默认只对public方法创建事务代理。
    • 解决:将方法改为public
  4. 数据库引擎不支持

    • 现象:使用 MySQL MyISAM 引擎。
    • 原因:MyISAM 不支持事务。
    • 解决:确保表引擎为 InnoDB。

四、 总结建议

  • 默认配置够用吗? 对于大多数 CRUD 场景,默认的REQUIRED传播行为和运行时异常回滚规则是足够的。
  • 何时需要自定义?
    • 涉及多数据源或复杂事务嵌套时,需仔细选择propagation
    • 高并发查询场景,添加readOnly = true提升性能。
    • 关键业务数据更新,务必设置rollbackFor = Exception.class
  • 分布式场景:@Transactional仅适用于单体应用或单数据库场景。微服务架构下需使用 Seata、TCC 或消息最终一致性方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询