SpringBoot 中的 @Transactional 事务基本作用及注意事项示例详解

 更新时间:2025年09月25日 10:03:35   作者:喝汽水的猫^  
@Transactional是SpringBoot中声明式事务管理的核心注解,通过注解简化事务控制,确保操作的原子性,支持异常回滚、隔离级别和传播行为配置,需注意代理模式、异常抛出及数据库支持等条件,避免事务失效,本文介绍SpringBoot @Transactional事务作用,感兴趣的朋友一起看看吧

前言

@Transactional 是 Spring 中用于声明式事务管理的核心注解,它可以简化事务控制逻辑,通过注解方式替代传统的编程式事务管理。在 Spring Boot 中,@Transactional 的使用尤为广泛,以下是其详细解析:

一、基本作用

@Transactional 用于标记某个方法或类需要被事务管理,Spring 会在方法执行前后自动开启、提交或回滚事务,确保操作的原子性(要么全成功,要么全失败)。

使用位置:

  • 方法上:仅对该方法生效
  • 类上:对类中所有公共方法生效(public)
  • 接口上:不推荐(可能因代理模式导致失效)

二、核心属性

@Transactional 有多个属性可配置,常用的包括:

属性名作用默认值
rollbackFor指定哪些异常触发回滚(类或数组)仅 RuntimeException 及其子类
noRollbackFor指定哪些异常不触发回滚
isolation事务隔离级别(控制并发数据可见性)Isolation.DEFAULT(数据库默认)
propagation事务传播行为(控制嵌套方法的事务归属)Propagation.REQUIRED
readOnly是否为只读事务(优化性能,适合查询操作)false
timeout事务超时时间(秒),超时后自动回滚-1(无超时)
value/transactionManager指定事务管理器(多数据源时使用)默认事务管理器

1. 异常回滚配置(rollbackFor/noRollbackFor)

  • 默认规则:仅对 RuntimeException 及其子类(非检查异常)回滚,对 Exception 及其子类(检查异常)不回滚。
  • 推荐配置:rollbackFor = Exception.class,确保所有异常都触发回滚:

示例:

@Transactional(rollbackFor = Exception.class) // 所有异常都回滚
public void saveData() throws Exception {
    // 业务逻辑
}
  • 特殊需求:指定不回滚的异常:

示例:

@Transactional(noRollbackFor = ArithmeticException.class)
public void process() {
    // 发生 ArithmeticException 不回滚,其他异常正常回滚
}

2. 隔离级别(isolation)

控制并发事务之间的数据可见性,可选值:

  • Isolation.DEFAULT:使用数据库默认隔离级别(推荐)
  • Isolation.READ_UNCOMMITTED:读未提交(最低隔离,可能脏读)
  • Isolation.READ_COMMITTED:读已提交(避免脏读,多数数据库默认)
  • Isolation.REPEATABLE_READ:可重复读(避免脏读、不可重复读,MySQL 默认)
  • Isolation.SERIALIZABLE:串行化(最高隔离,避免幻读,性能最低)

示例:

@Transactional(isolation = Isolation.READ_COMMITTED)
public void queryData() {
    // 事务内查询,只能看到已提交的数据
}

3.脏读(Dirty Read)

定义:一个事务读取到了另一个未提交事务修改的数据。

场景示例:

  • 事务 A:更新了一条记录但未提交
  • 事务 B:读取了事务 A 更新后的记录
  • 事务 A:由于某种原因回滚了操作
  • 结果:事务 B 读取到的数据是 “无效” 的(已被回滚)

危害:导致读取到临时且可能被撤销的数据,影响业务逻辑正确性。

避免方式:将事务隔离级别设置为 READ COMMITTED 或更高(REPEATABLE READ、SERIALIZABLE)。

MySQL 默认隔离级别是 REPEATABLE READ,已避免脏读。

4.幻读(Phantom Read)

定义:一个事务在两次查询中得到不同的结果集,因为另一个事务在两次查询之间插入或删除了数据。

场景示例:

  • 事务 A:查询年龄 > 20 的用户,得到 10 条记录
  • 事务 B:插入了一条年龄 = 25 的新用户并提交
  • 事务 A:再次执行相同查询,得到 11 条记录(多了一条 “幻影” 数据)

5. 传播行为(propagation)

控制嵌套方法的事务归属,核心值:

  • Propagation.REQUIRED(默认):如果当前有事务,则加入;否则新建事务。
  • Propagation.REQUIRES_NEW:无论当前是否有事务,都新建独立事务(原事务暂停)。
  • Propagation.SUPPORTS:如果当前有事务,则加入;否则以非事务方式执行。
  • Propagation.NOT_SUPPORTED:以非事务方式执行,若当前有事务则暂停。
  • Propagation.NEVER:必须在非事务环境执行,否则抛异常。
  • Propagation.MANDATORY:必须在事务环境执行,否则抛异常。
  • Propagation.NESTED:嵌套事务(依赖数据库支持,如 MySQL 的 SAVEPOINT)。

示例:独立事务场景

@Service
public class OrderService {
    @Autowired
    private LogService logService;
    @Transactional(rollbackFor = Exception.class)
    public void createOrder() {
        // 订单业务(主事务)
        logService.saveLog(); // 调用日志服务
    }
}
@Service
public class LogService {
    // 日志保存使用独立事务,即使订单回滚,日志仍会提交
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void saveLog() {
        // 保存日志
    }
}

6. 其他属性

  • readOnly = true:适用于纯查询方法,数据库可优化性能(如避免写锁):
@Transactional(readOnly = true)
public List<User> queryUsers() {
    return userMapper.selectAll();
}
  • timeout = 10:事务超时时间 10 秒,超时后自动回滚:
@Transactional(timeout = 10)
public void longTimeTask() {
    // 长时间任务,超时会回滚
}

三、事务生效条件

1.代理模式:Spring 事务基于 AOP 代理实现,需满足:

  • 方法必须是 public(非 public 方法注解可能失效)。
  • 需通过 Spring 容器的代理对象调用方法(同类中自调用可能失效,需特殊处理)。

2.异常处理:

  • 异常必须抛出到 @Transactional 标记的方法外(被捕获的异常不会触发回滚)。
  • 需符合 rollbackFor 配置的异常类型。

3.数据库支持:

  • 数据库必须支持事务(如 MySQL 的 InnoDB 引擎,MyISAM 不支持)。

四、常见问题

1.自调用事务失效:

@Service
public class UserService {
    public void methodA() {
        methodB(); // 自调用,事务可能失效
    }
    @Transactional
    public void methodB() {
        // 业务逻辑
    }
}

解决:通过 Spring 上下文获取代理对象调用,或使用 @EnableAspectJAutoProxy(exposeProxy = true) 暴露代理。

2.多线程事务不共享:

新线程中的方法不会加入当前事务,需手动协调事务。

3.错误的异常处理:

@Transactional
public void save() {
    try {
        // 业务逻辑
    } catch (Exception e) {
        // 异常被捕获,未抛出,事务不会回滚
    }
}

解决:捕获后需重新抛出异常,或手动调用 TransactionStatus.setRollbackOnly()。

五、总结

@Transactional 是 Spring Boot 中简化事务管理的强大工具,核心关注:

  • 异常回滚规则(rollbackFor)
  • 并发控制(isolation)
  • 嵌套事务关系(propagation)
    合理配置可确保数据一致性,同时需注意代理模式、异常处理等细节避免事务失效。

到此这篇关于SpringBoot 中的 @Transactional 事务详解及注意事项的文章就介绍到这了,更多相关SpringBoot @Transactional 事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • RocketMQ根据Tag进行消息过滤

    RocketMQ根据Tag进行消息过滤

    消费者订阅了某个主题后,Apache RocketMQ 会将该主题中的所有消息投递给消费者。若消费者只需要关注部分消息,可通过设置过滤条件在 Apache RocketMQ 服务端进行过滤,只获取到需要关注的消息子集,避免接收到大量无效的消息
    2023-02-02
  • Java SPI简单应用案例详解

    Java SPI简单应用案例详解

    这篇文章主要介绍了Java SPI简单应用案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Spring Boot Controller处理HTTP请求体的方法

    Spring Boot Controller处理HTTP请求体的方法

    Spring Boot提供了强大的机制来处理不同 Content-Type​ 的HTTP请求体,这主要依赖于 HttpMessageConverter​ 接口的各种实现,它们能够自动将请求体内容转换成Java方法参数,本文给大家介绍Spring Boot Controller处理HTTP请求体的方法,感兴趣的朋友一起看看吧
    2025-05-05
  • SpringCloud中的Consul详解

    SpringCloud中的Consul详解

    这篇文章主要介绍了SpringCloud中的Consul知识,本文使用的是docker-compose方式管理consul服务,直接启动即可,需要的朋友可以参考下
    2022-03-03
  • Spring Boot构建框架详解

    Spring Boot构建框架详解

    这篇文章主要为大家详细介绍了Spring Boot构建框架的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • Java案例使用集合方法实现统计任意字符串中字符出现的次数

    Java案例使用集合方法实现统计任意字符串中字符出现的次数

    这篇文章主要介绍了Java案例使用集合方法实现统计任意字符串中字符出现的次数,下面我们将用两种方法实现,需要的小伙伴可以参考一下文章具体内容
    2022-04-04
  • Java实现JWT登录认证的示例代码

    Java实现JWT登录认证的示例代码

    Java中我们可以使用诸如JJWT这样的库来生成和验证JWT,本文主要介绍了Java实现JWT登录认证的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-04-04
  • SpringMVC的REST风格的四种请求方式总结

    SpringMVC的REST风格的四种请求方式总结

    下面小编就为大家带来一篇SpringMVC的REST风格的四种请求方式总结。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 浅谈mybatis中的#和$的区别 以及防止sql注入的方法

    浅谈mybatis中的#和$的区别 以及防止sql注入的方法

    下面小编就为大家带来一篇浅谈mybatis中的#和$的区别 以及防止sql注入的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • Java Jar包项目内存设置方法举例

    Java Jar包项目内存设置方法举例

    这篇文章主要给大家介绍了关于Java Jar包项目内存设置方法的相关资料,文中通过代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01

最新评论