当前位置: 首页 > ops >正文

Spring Boot 中 @Transactional 解析

在 Spring Boot 开发中,@Transactional 注解是实现数据库事务管理的关键工具,它能有效确保数据操作的原子性、一致性、隔离性和持久性(ACID)。本文将详细介绍 @Transactional 的使用方法、核心属性、原理以及常见的坑和解决方案。

一、@Transactional 的基本使用

@Transactional 注解可以应用在类或方法上。当标注在类上时,该类中的所有公共方法都会被纳入事务管理;若标注在方法上,则仅对该方法进行事务管理。

使用时,首先要在 Spring Boot 启动类上添加 @EnableTransactionManagement 注解,以开启事务管理功能。例如:

@SpringBootApplication
@EnableTransactionManagement
public class YourApplication {public static void main(String[] args) {SpringApplication.run(YourApplication.class, args);}
}

然后在需要事务管理的 Service 类或方法上添加 @Transactional 注解。如下所示:

@Service
public class UserService {private final UserRepository userRepository;public UserService(UserRepository userRepository) {this.userRepository = userRepository;}@Transactionalpublic void createUser(User user) {userRepository.save(user);// 假设这里还有其他数据库操作// 如果任何操作失败,整个事务将回滚}
}
二、@Transactional 的核心属性
  • propagation:事务传播行为,定义了被调用方法的事务边界,默认值为 Propagation.REQUIRED。常见取值有 Propagation.REQUIRED(若当前有事务则加入,无则创建新事务)、Propagation.REQUIRES_NEW(创建新事务,挂起当前事务)、Propagation.SUPPORTS(有事务则加入,无则以非事务方式执行)等。
  • isolation:事务隔离级别,用于解决事务并发访问时的问题,默认值为 Isolation.DEFAULT。如 Isolation.READ_UNCOMMITTED(允许读取未提交数据,可能出现脏读等)、Isolation.READ_COMMITTED(只允许读取已提交数据,可避免脏读)等。
  • timeout:事务的超时时间,单位为秒,默认值为 - 1,表示无超时限制。
  • rollbackFor:指定需要回滚的异常类型数组,默认情况下,只有运行时异常和错误会导致事务回滚。
  • noRollbackFor:指定不需要回滚的异常类型数组。
三、@Transactional 的原理

@Transactional 注解的逻辑是通过动态代理来实现的。Spring Boot 会先扫描 spring - boot - autoconfigure 依赖包下的 META - INF/spring.factories,加载 TransactionAutoConfiguration 类,再经过一系列解析和加载操作,最终向 Spring 容器注册事务相关的切面逻辑,主要涉及 Pointcut(确定哪个类需要增强)、Advise(具体的事务处理逻辑,如根据异常进行提交或回滚)和 Advisor(封装 Pointcut 和 Advise)。然后根据切面逻辑,利用 JDK 或 CGLIB 生成动态代理类,当调用被 @Transactional 注解标注的方法时,实际上是通过代理类来处理事务。

四、@Transactional 常见陷阱及解决方案
  • 事务失效
    • 自调用陷阱:同一类中方法 A 调用带 @Transactional 的方法 B,事务未生效,因为 Spring 事务基于 AOP 代理实现,自调用会绕过代理。可将方法 B 移到另一个 Service 类中,或通过 AopContext.currentProxy () 调用(需开启 @EnableAspectJAutoProxy (exposeProxy = true))。
    • 异常被 “吞没”:默认只回滚 RuntimeException 和 Error,若捕获异常未重新抛出或抛出受检异常,事务不会回滚。可通过 @Transactional (rollbackFor = Exception.class) 明确指定回滚异常,或在 catch 块中抛出 RuntimeException。
    • 访问权限限制:@Transactional 标注在 private 或 protected 方法上无效,因为 Spring AOP 代理要求目标方法为 public。可将方法改为 public,或使用 AspectJ 模式。
  • 传播机制配置不当:例如在日志记录方法中误用 Propagation.REQUIRED,会导致业务事务回滚时日志也被回滚。应根据实际需求选择合适的传播行为,如日志记录方法可使用 Propagation.REQUIRES_NEW。
  • 隔离级别问题:默认隔离级别可能导致不可重复读等问题。可根据业务需求升级隔离级别,如使用 @Transactional (isolation = Isolation.REPEATABLE_READ),或结合悲观锁等机制优化。

总之,@Transactional 在 Spring Boot 事务管理中起着重要作用,了解其使用方法和原理,注意避开常见陷阱,才能更好地确保数据的一致性和完整性,提升系统的稳定性和可靠性。

http://www.xdnf.cn/news/17542.html

相关文章:

  • [Oracle] UNPIVOT 列转行
  • Linux kernel network stack, some good article
  • Day 37:早停策略和模型权重的保存
  • 《番外:Veda的备份,在某个未联网的旧服务器中苏醒……》
  • Mybatis学习之缓存(九)
  • 从零开始的云计算生活——第四十一天,勇攀高峰,Kubernetes模块之单Master集群部署
  • Seata
  • vue+django 大模型心理学智能诊断评测系统干预治疗辅助系统、智慧心理医疗、带知识图谱
  • EXISTS 替代 IN 的性能优化技巧
  • 前端灰度发布浅析
  • 【C++语法】输出的设置 iomanip 与 std::ios 中的流操纵符
  • 【stm32】EXTI外部中断
  • IoT/实现和分析 NB-IoT+DTLS+PSK 接入华为云物联网平台IoTDA过程,总结避坑攻略
  • 运维学习Day21——LAMP/LNMP 最佳实践
  • Python day 41
  • Linux 流编辑器 sed 详解
  • Linux-常用命令
  • Apache IoTDB 全场景部署:跨「端-边-云」的时序数据库 DB+AI 实战
  • 人工智能与农业:农业的革新
  • 超算中心的一台服务器上有多少个CPU,多少个核?
  • Spring JDBC
  • 构建轻量级Flask Web框架:从入门到实践
  • Spring Cloud Gateway 路由与过滤器实战:转发请求并添加自定义请求头(最新版本)
  • st.session_state 的存储机制
  • Docker中ES安装分词器
  • docker集群
  • USB 标准请求
  • gophis钓鱼流程
  • SSM+Dubbo+Zookeeper框架和springcloud框架,写业务的时候主要区别在哪?
  • 如何理解Tomcat、Servlet、Catanalina的关系