SpringBoot中事务失效的原因
SpringBoot中事务失效的原因
文章目录
- SpringBoot中事务失效的原因
- 一、事务方法非public修饰
- 二、非事务方法调用事务方法
- 三、事务方法的异常被捕获
- 四、事务异常类型不对
- 五、事务传播行为不对
- 六、没有被Spring管理
- 6.1、暴漏代理对象
- 6.2、使用代理对象
常见的事务失效原因包括如下六个
一、事务方法非public修饰
由于Spring的事务是基于AOP的方式结合动态代理来实现的。因此事务方法一定要是public的,这样才能便于被Spring做事务的代理和增强。
而且,在Spring内部也会有一个 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource
类,去检查事务方法的修饰符:
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {// Don't allow no-public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// 省略}
二、非事务方法调用事务方法
@Service
public class OrderService { public void createOrder(){// ... 准备订单数据// 生成订单并扣减库存insertOrderAndReduceStock();} @Transactionalpublic void insertOrderAndReduceStock(){// 生成订单insertOrder();// 扣减库存reduceStock();}
}
可以看到,insertOrderAndReduceStock
方法是一个事务方法,肯定会被Spring事务管理。Spring会给OrderService
类生成一个动态代理对象,对insertOrderAndReduceStock
方法做增加,实现事务效果。
但是现在createOrder
方法是一个非事务方法,在其中调用了insertOrderAndReduceStock
方法,这个调用其实隐含了一个this.
的前缀。也就是说,这里相当于是直接调用原始的OrderService中的普通方法,而非被Spring代理对象的代理方法。那事务肯定就失效了!
三、事务方法的异常被捕获
异常被捕获了但是没有往外抛异常,所以事务没有发现方法中出现错误,所以也就没有回滚
在这段代码中,reduceStock方法内部直接捕获了Exception类型的异常,也就是说方法执行过程中即便出现了异常也不会向外抛出。
而Spring的事务管理就是要感知业务方法的异常,当捕获到异常后才会回滚事务。
现在事务被捕获,就会导致Spring无法感知事务异常,自然不会回滚,事务就失效了。
四、事务异常类型不对
@Transactional(rollbackFor = RuntimeException.class)
public void createOrder() throws IOException {// ... // 准备订单数据// 生成订单insertOrder();// 扣减库存reduceStock();throw new IOException();
}
Spring的事务管理默认感知的异常类型是RuntimeException
,当事务方法内部抛出了一个IOException
时,不会被Spring捕获,因此就不会触发事务回滚,事务就失效了。
因此,当我们的业务中会抛出RuntimeException以外的异常时,应该通过@Transactional
注解中的rollbackFor
属性来指定异常类型:
@Transactional(rollbackFor = Exception.class)
五、事务传播行为不对
@Transactional
public void createOrder(){// 生成订单insertOrder();// 扣减库存reduceStock();throw new RuntimeException("业务异常");
}
@Transactional // 默认的是如果当前没有事务,自己创建事务,如果有事务则加入
public void insertOrder() {}
// 不管当前方法所在方法有没有都开启一个事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void reduceStock() {}
在示例代码中,事务的入口是createOrder()
方法,会开启一个事务,可以成为外部事务。在createOrder()方法内部又调用了insertOrder()
方法和reduceStock()
方法。这两个都是事务方法。
不过,reduceStock()
方法的事务传播行为是REQUIRES_NEW
,这会导致在进入reduceStock()
方法时会创建一个新的事务,可以成为子事务。insertOrder()
则是默认,因此会与createOrder()
合并事务。
因此,当createOrder
方法最后抛出异常时,只会导致insertOrder
方法回滚,而不会导致reduceStock
方法回滚,因为reduceStock
是一个独立事务。
所以,一定要慎用传播行为,注意外部事务与内部事务之间的关系。
六、没有被Spring管理
即当前类没有被SpringBoot扫描
第二种事务失效的解决方案:
上面的问题在于非事务方法中调用事务方法其中隐含了一个this.
的前缀, 虽然当前方法的事务也被代理类生成了,但是因为默认关键字的原因,调用的还是原来的是没有事务的方法.
所以我们现在要做的就是要找到被代理之后的类,然后再在方法中调用该方法
6.1、暴漏代理对象
在启动类上添加注解,暴露代理对象:
@EnableAspectJAutoProxy(exposeProxy = true)
6.2、使用代理对象
通过AopContext拿到当前类的代理对象,然后调用对应方法
IUserCouponService userCouponService = (IUserCouponService) AopContext.currentProxy();
userCouponService.insertCouponAndCheck(userId, coupon, null);
注意:何时会产生代理对象?只有代理对象在调用方法的时候才会将当前代理对象暴漏在当前线程中。
相关文章:

SpringBoot中事务失效的原因
SpringBoot中事务失效的原因 文章目录 SpringBoot中事务失效的原因一、事务方法非public修饰二、非事务方法调用事务方法三、事务方法的异常被捕获四、事务异常类型不对五、事务传播行为不对六、没有被Spring管理6.1、暴漏代理对象6.2、使用代理对象 常见的事务失效原因包括如下…...
Webstorm的一些常用快捷键
下面是Webstorm的一些常用快捷键: ctrl shift n: 打开工程中的文件,目的是打开当前工程下任意目录的文件。ctrl j: 输出模板ctrl b: 跳到变量申明处ctrl alt T: 围绕包裹代码(包括zencoding的Wrap with Abbreviation)ctrl []: 匹配 {}[]ctrl F1…...

系统集成项目成本管理
在项目中,成本是指项目活动或其组成部分的货币价值或价格,包括为实施、完成或创造该活动或其组成部分所需资源的货币价值。具体的成本一般包括直接工时、其他百接费用、间接工时、其他间接费用以及采购价格。 项目全过程所耗用的各种成本的总和为项目成本…...

Spring Boot整合ES的两种方式
使用Spring Data Elasticsearch Starter 在Spring Boot中整合Elasticsearch的方式之一是使用Elasticsearch的官方Spring Data Elasticsearch Starter。该Starter提供了对Elasticsearch的高级集成,简化了配置和管理Elasticsearch客户端。 下面是使用Spring Data E…...
Ajax_3 Ajax原理+ (XMLHttpRequest + Promise )+ 封装一个axios插件库,实现功能。
Ajax_3 Ajax原理 01-Ajax原理-XMLHttpRequest 使用XMLHttpRequest 步骤: 创建XMLHttpRequest对象配置请求方法请求url网址监听loadend事件,接受响应结果发起请求 需求:使用XMLHttpRequest对象与服务器通信 代码示例 // 1. 创建 XMLHttpReq…...

计算机网络(7) --- UDP协议和TCP协议
计算机网络(6) --- https协议_哈里沃克的博客-CSDN博客https协议https://blog.csdn.net/m0_63488627/article/details/132112683?spm1001.2014.3001.5501 目录 1.补充知识 1.PORT端口号 2.端口号范围划分 3.知名端口号 2.UDP协议 1.UDP报头 2.U…...

Jenkins 修改默认管理员帐号
1、新增一个新的超级管理员用户,并验证能正常登录 2、进入 Jenkins 用户管理目录: /data/software/jenkins/users 3、修改超级管理文件夹的名称为其他名称,如:mv admin_*** ifadm_*** 4、重启Jenkins容器...

FK-坦克大战制作(一)菜单制作
1、Cocos Creator新建2d项目 2.在资源管理器中新建场景menu 新建scences文件夹》新建场景》改名为menu 3.在层级管理器的Canvas下新建Layout节点,并在此节点下新建Label标签 4.双击Label,在属性检查器中进行编辑 5. 添加动画:(对文本进行放大…...

39.利用matlab寻找素数(matlab程序)
1.简述 MATLAB嵌套循环允许使用一个循环在另一循环内,下面用一个嵌套循环来把所有从1到100的素数显示出来。 2.代码 %% 学习目标:寻找素数 clear sum5; %求0~100素数之和 ss0; %用来标定是否是素数,0表示不是 p…...

卡尔曼滤波算法demo
代码 learn_kalman.py #codingutf-8 import numpy as np import time from kinematic_model import freedrop from controller import kalman_filterimport matplotlib.pyplot as plt # 支持中文 import matplotlib as mpl mpl.rcParams[font.family]SimHei plt.rcParams[a…...

MySQL游标(二十九)
二八佳人体似酥,腰悬利剑斩愚夫,虽然不见人头落,暗里教君骨髓枯。 上一章简单介绍了MySQL流程控制(二十八) ,如果没有看过,请观看上一章 一. 游标 一.一 什么是游标 虽然我们也可以通过筛选条件 WHERE 和 HAVING,或者是限定返回记录的关键…...

内生安全构建数据存储
一、数据安全成为防护核心,存储安全防护不容有失 1、数据作为企业的核心资产亟需重点保护,数据安全已成网络空间防护核心 2、国家高度重视关键信息基础设施的数据安全,存储安全已成为审核重点 二、存储安全是数据安全的关键一环,应…...

Docker+Consul+Registrator 实现服务注册与发现
第四阶段 时 间:2023年8月8日 参加人:全班人员 内 容: DockerConsulRegistrator 实现服务注册与发现 目录 一、服务注册中心引言 CAP理论是分布式架构中重要理论: 二、服务注册中心软件 (一)Zoo…...

深入学习JVM —— GC垃圾回收机制
前言 前面荔枝已经梳理了有关JVM的体系结构和类加载机制,也详细地介绍了JVM在类加载时的双亲委派模型,而在这篇文章中荔枝将会比较详细地梳理有关JVM学习的另一大重点——GC垃圾回收机制的相关知识,重点了解的比如对象可达性的判断、四种回收…...
Centos7.6 + Apache Ranger 2.4.0编译(docker方式)
目录 一、Ranger简介 1、组件列表 2、支持的数据引擎服务 二、主机环境准备 1、关闭防火墙 2、关闭SELINUX 3、安装docker 4、下载Ranger源码包 5、下载Maven安装包 三、编译Ranger源码 1、修改官方包中的build_ranger_using_docker.sh 2、运行脚本编译 3、编译检…...
LVS-DR模式集群配置
四台虚拟机 node1:128 node2:135 RS端: node3:130 node4:132 [rootnode2 ~]# yum install -y ipvsadm #配置LVS虚拟IP,没有ifconfig命令则先安装 [rootnode2 ~]# yum install net-tools -y #配置VIP [root…...
【数据分析】pandas( 二)
目录 简介: 一,1.1来自Series字典或字典 1.2 来自ndarray或者列表的字典: 1.3来自结构化或记录数组; 1.4来自字典列表: 1.4来自元组的字典: 1.5 来自Series 二,代替构造函数: 2.1DataFram…...

ffmpeg工具实用命令
说明:ffmpeg是一款非常好用的媒体操作工具,包含了许多对于视频、音频的操作,有些视频播放器里面实际上就是使用了ffmpeg。本文介绍ffmpeg的使用以及一些较为实用的命令。 安装 ffmpeg是命令行操作的,不需要安装,可在…...
zabbix API笔记
博客园原文 python简单demo 输出id为111主机的主机群组信息 import requests import json request_headers {"Content-Type": "application/json"} zabbix_url "http://xxx.xxx.xxx.xxx:8080/zabbix/api_jsonrpc.php" get_hostgroup_from_h…...
[HDLBits] Mt2015 q4a
Module A is supposed to implement the function z (x^y) & x. Implement this module. module top_module (input x, input y, output z);assign z(x^y)&x; endmodule...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...