事务失效问题

1,事务方法非public修饰


由于Spring的事务是基于AOP的方式结合动态代理来实现的。因此事务方法一定要是public的,这样才能便于被Spring做事务的代理和增强。

2,非事务方法调用事务方法


@Service
public class OrderService {public void createOrder(){// ... 准备订单数据// 生成订单并扣减库存insertOrderAndReduceStock();}@Transactionalpublic void insertOrderAndReduceStock(){// 生成订单insertOrder();// 扣减库存reduceStock();}
}

可以看到,insertOrderAndReduceStock方法是一个事务方法,肯定会被Spring事务管理。Spring会给OrderService类生成一个动态代理对象,对insertOrderAndReduceStock方法做增加,实现事务效果。

但是现在createOrder方法是一个非事务方法,在其中调用了insertOrderAndReduceStock方法,这个调用其实隐含了一个this.的前缀。也就是说,这里相当于是直接调用原始的OrderService中的普通方法,而非被Spring代理对象的代理方法。那事务肯定就失效了!

解决方案: 使用代理对象调用师傅方法

3,事务方法的异常被捕获了

而Spring的事务管理就是要感知业务方法的异常,当捕获到异常后才会回滚事务。

现在事务被捕获,就会导致Spring无法感知事务异常,自然不会回滚,事务就失效了

4,事务异常类型不对


Spring的事务管理默认感知的异常类型是RuntimeException,当事务方法内部抛出了一个IOException时,不会被Spring捕获,因此就不会触发事务回滚,事务就失效了。

5,事务传播行为不对 

@Servicepublic class OrderService {@Transactionalpublic void createOrder(){// 生成订单insertOrder();// 扣减库存reduceStock();throw new RuntimeException("业务异常");}@Transactionalpublic void insertOrder() {}@Transactional(propagation = Propagation.REQUIRES_NEW)public void reduceStock() {}}

在示例代码中,事务的入口是createOrder()方法,会开启一个事务,可以成为外部事务。在createOrder()方法内部又调用了insertOrder()方法和reduceStock()方法。这两个都是事务方法。

不过,reduceStock()方法的事务传播行为是REQUIRES_NEW,这会导致在进入reduceStock()方法时会创建一个新的事务,可以成为子事务。insertOrder()则是默认,因此会与createOrder()合并事务。

因此,当createOrder方法最后抛出异常时,只会导致insertOrder方法回滚,而不会导致reduceStock方法回滚,因为reduceStock是一个独立事务。

6,没有被Spring管理 

 
//  @Servicepublic class OrderService {@Transactionalpublic void createOrder(){// 生成订单insertOrder();// 扣减库存reduceStock();throw new RuntimeException("业务异常");}@Transactionalpublic void insertOrder() {}@Transactionalpublic void reduceStock() {}}

OrderService类没有添加@Service注解,因此就没有被Spring管理。你在方法上添加的@Transactional注解根本不会有人帮你动态代理,事务自然失效。

解决办法: 


既然事务失效的原因是方法内部调用走的是this,而不是代理对象。那我们只要想办法获取代理对象不就可以了嘛。

 我们可以借助AspectJ来实现。

1,引入AspectJ依赖:

<!--aspecj-->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId>
</dependency>

2,暴露代理对象

在启动类上添加注解,暴露代理对象

3, 使用代理对象调用

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

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

相关文章

0201安装报错-hbase-大数据学习

1 基础环境简介 linux系统&#xff1a;centos&#xff0c;前置安装&#xff1a;jdk、hadoop、zookeeper&#xff0c;版本如下 软件版本描述centos7linux系统发行版jdk1.8java开发工具集hadoop2.10.0大数据生态基础组件zookeeper3.5.7分布式应用程序协调服务hbase2.4.11分布式…

SpringBoot整合Redis实现分布式锁

SpringBoot整合Redis实现分布式锁 分布式系统为什么要使用分布式锁&#xff1f; 首先&#xff0c;分布式系统是由多个独立节点组成的&#xff0c;这些节点可能运行在不同的物理或虚拟机器上&#xff0c;它们通过网络进行通信和协作。在这样的环境中&#xff0c;多个节点可能同…

JavaWeb笔记 --- 一JDBC

一、JDBC JDBC就是Java操作关系型数据库的一种API DriverManager 注册驱动可以不写 Class.forName("com.mysql.jdbc.Driver"); Connection Statement ResultSet PrepareStatement 密码输入一个SQL脚本&#xff0c;直接登录 预编译开启在url中 数据库连接池

git搜索历史上曾经的文本内容

文章目录 问题在命令行搜索历史内容参考 问题 我们知道&#xff0c;github有文本搜索功能&#xff1a; 比如想搜哪些文件内容包括 aaa &#xff0c;在搜索框中输入 aaa &#xff1a; 但是&#xff0c;如果是历史上曾经有过的文本&#xff0c;这个办法貌似不行。 比如文件 tes…

蓝桥杯集训·每日一题2024 (二分,双指针)

前言&#xff1a; 开学了&#xff0c;平时学习的压力也逐渐大起来了&#xff0c;不过还算可以接受&#xff0c;等到后面阶段考的时候就不一样了&#xff0c;我目前为了转专业退选了很多课&#xff0c;这些课我都需要花时间来刷绩点&#xff0c;不然保研就没有竞争力了。我自己会…

idea配置汇总【2023】最新外观配置和常规操作配置

界面 如果是IDEA请移步去其他人之前的文章看已经烂大街了&#xff0c;这是最新版的一些新功能的配置研究&#xff0c;毕竟天天看它不好看点怎么能行 ①tool windows 在新版&#xff08;不一定是当前年份的最新版&#xff09;idea中针对界面tool window有了新的优化&#xff0c…

Unity用Shader将一张图片变成描边图片素描风格。

环境&#xff1a; unity2021.3.x 效果&#xff1a; 实现核心思路(shader)&#xff1a; fixed4 frag (v2f i) : SV_Target {fixed4 col tex2D(_MainTex, i.uv);// 调整相似度bool isRedMatch abs(col.r - _TargetColor.r) < 0.15;bool isGreenMatch abs(col.g - _Target…

读《文明之光》第1册总结

人类几千年的文明史和地球的历史相比&#xff0c;实在是太短暂了&#xff0c;大约相当于几分钟和一年的关系。人类已经走过的路&#xff0c;相比今后要走的漫漫长路&#xff0c;只能算是刚刚起步。如果跳出一个个具体事件&#xff0c;站在历史的高度去看&#xff0c;我们会发现…

尚硅谷JavaScript高级学习笔记

01 准备 JavaScript中函数是对象。我们后续描述构造函数的内存模型时&#xff0c;会将构造函数称为构造函数对象。 02 数据类型 typeof 运算符来查看值的类型&#xff0c;它返回的是类型的字符串值 会做数据转换 03 相关问题 04数据_变量_内存 05相关问题1 06相关问题2 …

设计模式大题做题记录

设计模式大题 09年 上半年&#xff1a; 09年下半年 10年上半年 10年下半年 11年上半年 11年下半年 12年上半年 12年下半年 13年上半年 13年下半年

C++进阶之路---继承(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、继承与友元 友元关系不能继承&#xff0c;也就是说基类友元不能访问子类私有和保护成员。 class Student; class Per…

2007-2022年上市公司迪博内部控制评价缺陷数量数据

2007-2022年上市公司迪博内部控制评价缺陷数量数据 1、时间&#xff1a;2007-2022年 2、范围&#xff1a;上市公司 3、指标&#xff1a;证券代码、证券简称、辖区、证监会行业、申万行业、是否存在财报内控重大缺陷、财报内控重大缺陷数量、是否存在财报内控重要缺陷、财报内…