在 Spring Boot 项目开发中,声明式事务管理通过 @Transactional 注解提供了极大的便利。

但许多开发者都曾遇到过事务不生效的困扰。

本文将详细分析导致 Spring Boot 事务失效的八大常见情况,并提供相应的解决方案。

1. 数据库引擎不支持事务

问题分析:这是最根本的原因。如果数据库存储引擎本身不支持事务(如 MySQL 的 MyISAM),那么无论 Spring 如何配置,事务都不会生效。

解决方案

  • 确保你的数据库表使用支持事务的引擎,如 MySQL 的 InnoDB
  • 建表时指定存储引擎:CREATE TABLE ... ENGINE=InnoDB;

2. 事务方法非 public 修饰

问题分析@Transactional 基于 Spring AOP 实现,而 AOP 代理默认无法拦截非 public 方法。

@Service
public class UserService {@Transactional // 失效!private void createUser(User user) {userMapper.insert(user);}
}

解决方案

  • 始终将 @Transactional 注解应用于 public 方法上

3. 自调用问题(Within-Class Invocation)

问题分析:这是最常见且最容易踩坑的原因。当一个类中的非事务方法调用同一个类中的 @Transactional 方法时,事务不会生效。

@Service
public class UserService {public void createUser(User user) {// 一些非事务操作this.insertUser(user); // 自调用,事务失效!}@Transactionalpublic void insertUser(User user) {userMapper.insert(user);// 如果这里出现异常,事务不会回滚}
}

解决方案

  • 推荐方案:将事务方法抽取到另一个 Service 类中
  • 通过 ApplicationContext 获取代理对象调用(不优雅)
  • 使用 AspectJ 模式的事务管理(配置复杂)

4. 异常类型不正确或被捕获

问题分析@Transactional 默认只在抛出运行时异常(RuntimeException)和 Error 时回滚。

@Transactional
public void method() throws Exception {// 数据库操作throw new Exception("受检异常"); // 事务不会回滚!
}

另一个陷阱:异常被捕获但未重新抛出

@Transactional
public void method() {try {int i = 1 / 0; // 抛出 RuntimeException} catch (Exception e) {e.printStackTrace(); // 只是打印,事务不会回滚!}
}

解决方案

  • 使用 rollbackFor 属性指定回滚的异常类型:
@Transactional(rollbackFor = Exception.class)
  • 在 catch 块中重新抛出运行时异常

5. 传播行为(Propagation)设置不当

问题分析:错误配置传播行为会导致意外结果。

@Transactional(propagation = Propagation.NOT_SUPPORTED) // 不以事务运行
public void method() {// 这里没有事务
}

解决方案

  • 根据业务需求正确配置传播行为
  • 理解各种传播行为的含义:
    • REQUIRED(默认):支持当前事务,不存在则新建
    • REQUIRES_NEW:新建事务,挂起当前事务
    • NOT_SUPPORTED:非事务方式执行
    • NEVER:非事务方式执行,存在事务则抛出异常

6. 未被 Spring 容器管理

问题分析:如果类没有加上 @Service, @Component 等注解,它就不是 Spring Bean,其上的 @Transactional 注解不会被扫描。

// 缺少 @Service 注解
public class UserService {@Transactional // 失效!public void createUser(User user) {// ...}
}

解决方案

  • 确保类被 Spring 管理,添加适当的注解

7. 多线程环境下调用

问题分析:事务信息存储在 ThreadLocal 中,新线程中的操作不属于原事务。

@Transactional
public void method() {new Thread(() -> {userMapper.insert(user); // 不在事务中!}).start();
}

解决方案

  • 避免在事务方法中创建异步线程进行数据库操作
  • 使用分布式事务解决方案处理跨线程事务

8. 配置问题

问题分析

  • 未开启事务管理(虽然 Spring Boot 会自动配置)
  • 多数据源未正确配置事务管理器

解决方案

  • 确保配置了 @EnableTransactionManagement(Spring Boot 通常自动配置)
  • 多数据源时为每个数据源配置对应的事务管理器:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}
  • 使用 @Transactional(value = "txManagerName") 指定事务管理器

事务调试技巧

开启事务调试日志,在 application.properties 中添加:

logging.level.org.springframework.transaction.interceptor=TRACE
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG

这将帮助你看清事务何时开启、回滚或提交。

总结

Spring Boot 事务失效通常由以上八大原因导致,其中自调用问题最为常见。要确保事务正常工作,需要:

  1. 使用支持事务的数据库引擎(如 InnoDB)
  2. @Transactional 应用于 public 方法
  3. 避免自调用,将事务方法放在不同类中
  4. 正确处理异常,确保异常能够触发回滚
  5. 正确配置传播行为
  6. 确保 Bean 被 Spring 管理
  7. 避免多线程事务问题
  8. 检查事务相关配置

希望本文能帮助你有效解决 Spring Boot 中的事务失效问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97818.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97818.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/97818.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构:顺序栈与链栈的原理、实现及应用

数据结构详解:顺序栈与链栈的原理、实现及应用 1. 引言:栈的核心概念 栈(Stack)是一种重要的线性数据结构,它遵循后进先出(Last In First Out, LIFO)的原则。这意味着最后一个被添加到栈中的元素…

apipost 8.x 脚本循环调用接口

apipost 8.x 脚本循环调用接口背景实现先说整体逻辑:最后背景 上周为了找某OA 偶尔出现的诡异现象,需要用测试工具来压测,看看这个问题能否重现。以前用过Jmeter,但是没有装,正好有个国产的apipost看看如何&#xff1…

STM32 - Embedded IDE - GCC - 使用 GCC 链接脚本限制 Flash 区域

导言如上所示,Keil限制flash区域只需要在IROM1里将Start框框与Size框框填入具体信息即可。比如bootloader程序一般从0x8000000开始,大小0x10000(64KB)。此时,flash的范围被限制在0x8000000 ~ 0x800FFFF。 另外&#xf…

Jenkins和Fastlane的原理、优缺点、用法、如何选择

Jenkins 和 Fastlane 是软件开发中用于自动化流程的工具一、Jenkins实现自动化打包1.1具体实现步骤安装与配置:首先在服务器上安装 Jenkins,可以通过官方提供的安装包进行安装,支持多种操作系统。安装完成后,通过 Web 界面进行初始…

DOM常见的操作有哪些?

1.DOM文档对象模型(DOM)是HTML和XML文档的编程接口它提供了对文档结构化表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容任何HTML或XML文档都可以用DOM表示一个由节点构成的层级结…

【Kubernetes】知识点3

25. 说明Job与CronJob的功能。答:Job:一次性作业,处理短暂的一次性任务,仅执行一次,并保证处理的一个或者多个 Pod 成功结束。CronJob:周期性作业,可以指定每过多少周期执行一次任务。26. Kuber…

LINUX-网络编程-TCP-UDP

1.目的:不同主机,进程间通信。2.解决的问题1)主机与主机之间物理层面必须互相联通。2)进程与进程在软件层面必须互通。IP地址:计算机的软件地址,用来标识计算机设备MAC地址:计算机的硬件地址&am…

目标检测定位损失函数:Smooth L1 loss 、IOU loss及其变体

Smooth L1 Loss 概述 Smooth L1 Loss(平滑 L1 损失),是一个在回归任务,特别是计算机视觉中的目标检测领域(如 Faster R-CNN, SSD)非常核心的损失函数。 xxx 表示模型的预测值,yyy 表示真实值&am…

Android开发之fileprovider配置路径path详细说明

第一步在清单文件配置fileprovider属性<providerandroid:name"androidx.core.content.FileProvider"android:authorities"${applicationId}.fileprovider"android:exported"false"android:grantUriPermissions"true"><meta-d…

【ComfyUI】图像描述词润色总结

在 ComfyUI 的工作流中&#xff0c;图像反推描述词能帮我们从图像里抽取语义信息&#xff0c;但这些原始描述往往还显得生硬&#xff0c;缺乏创意或流畅性。为了让提示词更自然、更有表现力&#xff0c;就需要“润色”环节。润色节点的任务&#xff0c;不是重新生成描述&#x…

java面试中经常会问到的IO、NIO问题有哪些(基础版)

文章目录一、IO 基础与分类二、NIO 核心组件与原理三、NIO 与 BIO 的实战对比四、AIO 与 NIO 的区别五、Netty 相关&#xff08;NIO 的高级应用&#xff09;总结Java 中的 IO&#xff08;输入输出&#xff09;和 NIO&#xff08;非阻塞 IO&#xff09;是面试中的重要考点&#…

时序数据库选型指南:如何为工业场景挑选最强“数据底座”

工业4.0时代&#xff0c;工厂化身为巨大的数据生产中心。数以万计的传感器、PLC和设备每时每刻都在产生着海量的时间序列数据&#xff08;Time-Series Data&#xff09;&#xff1a;温度、压力、流速、振动、设备状态……这些带时间戳的数据是工业互联网的血液&#xff0c;蕴含…

【排序算法】冒泡 选排 插排 快排 归并

一、冒泡排序// 冒泡排序var bubbleSort function (arr) {const len arr.length;for (let i 0; i < len; i) {let isSwap false;for (let j 0; j < len - 1; j) {// 每一次遍历都要比较相邻元素的大小&#xff0c;如果满足条件就交换位置if (arr[j] > arr[j 1])…

电子病历空缺句的语言学特征描述与自动分类探析(以GPT-5为例)(中)

语言学特征刻画(特征库) 句法特征 句法特征是识别 SYN 类电子病历空缺句的核心语言学维度,其量化分析通过构建依存句法结构的形式化指标,实现对语法不完整性的客观描述。该类特征主要包括依存树不完备指标、谓词-论元覆盖率及从属连词未闭合三类核心参数,共同构成 SYN 类…

InnoDB存储引擎-事务

1. 事务概述事务可由一条简单的SQL语句组成,也可以由一组复杂的SQL语句组成. 事务是访问并更新数据库中各种数据项的一个程序执行单元. 在事务中的操作, 要么都做修改, 要么都不做. 对于 InnoDB存储引擎而言, 其默认的事务隔离级别 RR , 完全遵循和满足了事务的 ACID 特性. 1.1…

web项目的目录结构

web项目的目录结构 WEB-INF 存放class文件、jar文件和配置文件&#xff0c;对于用户来说该文件夹是不可见的WEB-INF/web.xml web应用程序的描述文件&#xff0c;用来配置资源&#xff0c;如servlet、过滤器、监听器等WEB-INF/classes 用于存放class文件&#xff0c;也是该web应…

数据结构_队列Queue(C语言实现)

一、队列的基本概念 1.队列定义 队列是一种先进先出的线性表数据结构&#xff08;First in First out&#xff09;,现实中的例子就是&#xff0c;排队购票&#xff0c;先排队的先购票&#xff0c;购完票之后直接从这个队中离开&#xff0c;后来的在这个队后面排队&#xff0c;这…

C++对CPU缓存的合理利用

缓存体系 在计算机的体系结构中,存储速度是分了好几层: CPU缓存,又分成了L1/L2/L3等多层缓存,我们暂时看成同一层。访问速度最快 内存,访问速度次之,大概是CPU缓存的几十分之一 硬盘,访问速度最慢,是内存访问速度的几十分之一 所以,在计算机体系结构中,把下一层的数…

贝叶斯定理:理解概率更新与实际场景应用

贝叶斯定理及其应用&#xff1a;从基础到实战 贝叶斯定理&#xff08;Bayes’ Theorem&#xff09;是概率论中最基础也是最强大的工具之一。它通过将先验知识与新证据结合&#xff0c;能够帮助我们在不确定的情况下做出更加精准的判断。本文将从贝叶斯定理的核心概念、公式开始…

组件之间的传递参数传递(常用父向子传递)

现在&#xff0c;有子组件<MdsWxSourceDetailref"mdsWx":rank-obj"activeRankObj":media-name"activeObj.mediaName" :error-info"activeErrorInfo" ></MdsWxSourceDetail>以上代码在MdsIndexRankDetail&#xff0…