Spring 事务失效的场景

news2024/11/16 5:23:30

1、private、final、static 方法

@Transactional 注解标注的方法的访问权限必须是 public;

@Transactional 注解标注的方法不能被 final、static 修饰,被标注的方法必须是可覆盖的。这是因为事务底层使用的是 aop,而 aop 使用的是代理模式。代理模式生成的代理类无法重写被 final、static 修饰的方法。而 private 方法对子类不可见。

2、非事务方法调用

非事务方法调用事务方法,事务方法会失效。

public void transfer() {
    String sql = "update `test`  set money = money + 100 where id = 1;";
    jdbcTemplate.update(sql);
    reduce();
}

@Transactional
public void reduce() {
    String sql = "update `test`  set money = money - 100 where id = 2;";
    jdbcTemplate.update(sql);
    int i = 1 / 0;
}
复制代码

这种情况两个方法的操作都不会进行回滚。reduce() 方法相当于 this.reduce(),而 this 不是代理对象,所以 reduce 方法事务失效。

解决方案也有几种,比如:将事务方法移动到另外一个类中、在本类中注入自己、使用 @EnableAspectJAutoProxy(exposeProxy = true) + AopContext.currentProxy()

小杰这里使用第二种方式。

@Autowired
private TestServiceImpl serviceImpl;

public void transfer() {
    String sql = "update `test`  set money = money + 100 where id = 1;";
    jdbcTemplate.update(sql);
    serviceImpl.reduce();
}

@Transactional
public void reduce() {
    String sql = "update `test`  set money = money - 100 where id = 2;";
    jdbcTemplate.update(sql);
    int i = 1 / 0;
}
复制代码

这样 reduce() 方法就不会事务失效,所以发生异常会进行回滚。但 transfer 就不是个事务方法,所以不会回滚。

3、将异常处理掉

 @Transactional
 public void transfer() {
     String sql = "update `test`  set money = money + 100 where id = 1;";
     jdbcTemplate.update(sql);
     //serviceImpl.reduce();
     try {
         int i = 1 /0;
     } catch (Exception e) {
        
     }
 }
复制代码

4、抛出的异常不在回滚范围内

 @Transactional
 public void transfer() throws Exception {
     String sql = "update `test`  set money = money + 100 where id = 1;";
     jdbcTemplate.update(sql);
     //serviceImpl.reduce();
     try {
         int i = 1 /0;
     } catch (Exception e) {
         throw new Exception(e);
     }
 }
复制代码

默认情况下,Spring 事务只有遇到 RuntimeException 以及 Error 时才会回滚,在遇到检查型异常时是不会回滚的,比如 IOException、TimeoutException。所以,一般情况下都需要使用 rollbackFor参数指定回滚异常类,比如:@Transactional(rollbackFor = Exception.class)

5、使用错误的传播行为

@Transactional(rollbackFor = Exception.class)
public void transfer() {
    String sql = "update `test`  set money = money + 100 where id = 1;";
    jdbcTemplate.update(sql);
    serviceImpl.reduce();
}

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void reduce() {
    String sql = "update `test`  set money = money - 100 where id = 2;";
    jdbcTemplate.update(sql);
    int i = 1 / 0;
}
复制代码

这种写法会使 reduce 方法事务失效,出现异常不会回滚。这是因为使用了 NOT_SUPPORTED 的传播行为,该行为的特性是:以非事务方式运行,如果当前存在事务,则把当前事务挂起。而 transfer 方法会进行事务回滚,这是因为 reduce 方法的异常会往上抛,被 transfer 感知到,进行了事务回滚。

6、多线程调用

@Transactional(rollbackFor = Exception.class)
public void transfer() throws InterruptedException {
    String sql = "update `test`  set money = money + 100 where id = 1;";
    jdbcTemplate.update(sql);
    new Thread(() ->{
        serviceImpl.reduce(jdbcTemplate);
    }).start();
    Thread.sleep(1000);
}

@Transactional(rollbackFor = Exception.class)
public void reduce(JdbcTemplate jdbcTemplate) {
    String sql = "update `test`  set money = money - 100 where id = 2;";
    jdbcTemplate.update(sql);
    int i = 1 / 0;
}
复制代码

从示例代码中,可以看到事务方法 transfer 调用了事务方法 reduce,而 reduce 方法是开启了一个新线程调用的。这样会导致 reduce 方法不会加入到 transfer 事务中,reduce 方法会重新创建一个新事务。 这是因为 Spring 的事务是通过数据库连接来创建的,同一个事务,只能用同一个数据库连接。而多线程场景下,拿到的数据库连接是不一样的,即会导致获取到的不同事务。既然是两个事务,则没办法进行统一回滚。

7、数据库引擎不支持事务

比如 Mysql 的 MyISAM引擎就不支持事务。

8、代理类过早实例化

@Service
public class TestServiceImpl implements BeanPostProcessor, Ordered {

    @Autowired
    private TestServiceImpl serviceImpl;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional(rollbackFor = Exception.class)
    public void transfer()  {
        String sql = "update `test`  set money = money + 100 where id = 1;";
        jdbcTemplate.update(sql);
        serviceImpl.reduce(jdbcTemplate);
    }

    private void reduce(JdbcTemplate jdbcTemplate) {
        String sql = "update `test`  set money = money - 100 where id = 2;";
        jdbcTemplate.update(sql);
        int i = 1 / 0;
    }


    @Override
    public int getOrder() {
        return 1;
    }
}
复制代码

当代理类的实例化早于 AbstractAutoProxyCreator后置处理器,就无法被AbstractAutoProxyCreator后置处理器进行AOP增强。

上面 8 种事务失效场景中,需要我们平常注意的只有 2、3、4、5。

  • 如你对本文有疑问或本文有错误之处,欢迎评论留言指出。如觉得本文对你有所帮助,欢迎点赞和关注。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式为何钟爱SourceInsight,主要因为这个功能~

已剪辑自: https://mp.weixin.qq.com/s/F-gafwbZswpnY8EaCz8HxQ 不管是玩单片机还是嵌入式linux,只要是与硬件结合比较紧密的部分目前基本上还是C语言,当然了,不知道以后C语言会不会被取代,即便哪天被某种更加优秀的语言取代&…

m基于matlab的MIMO信道容量分析,对比了不同天线数量;非码本预编码SVD,GMD;码本预编码DFT,TxAA以及空间分集

目录 1.算法概述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法概述 MIMO信道容量 平均功率分配的MIMO信道容量:通过Matlab仿真在加性高斯白噪声情况下的SISO (1*1)、SIMO(1*6)、MISO(4*1)、MIMO(3*3)、MIMO(4*4)系统的…

VMware Explore 2022 China,赋能中国企业加速实现云智能

全球领先的企业软件创新者VMware(NYSE: VMW)的年度技术盛会—— VMware Explore 2022 China于11月8日正式举行。本届大会以“探索多云宇宙”为主题,汇聚云计算领域的顶尖技术专家和创新者,通过150多场解决方案演讲、围绕云基础架构…

[附源码]Python计算机毕业设计超市团购平台

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

JuiceFS 使用效果及注意事项

以某线上集群为例,数据规模:每天写入 5TB,数据储存 30 天,热数据储存一周,节点数量:5 个热节点,15 个冷节点。 采用 JuiceFS 后,热节点保持不变,冷节点从 15 个降到了 1…

[b01lers2020]Life on Mars (难发现的sql注入)

[b01lers2020]Life on Mars 打开界面以后,查看各种都没有提示,果断扫描目录,但也是没获得什么。 到这里只能burp抓个包看看 抓包两个界面发现了get传参,考虑是否存在sql注入 尝试额以后发现只返回了一个1,试一下别的引…

Nginx显示500错误原因和解决方法

文章目录1.背景2.Nginx 常见的几种报错3. 解决500错误1.背景 最近在操作nginx 的时候出现了 Nginx 500 内部错误,在此记录一下原因,项目采用的是前后端分离方式,后端SpringBoot ,前端是Vue 部署到Nginx 下。 2.Nginx 常见的几种…

从水质监测运维工程师转行软件测试,武汉校区小哥哥除了收获10k高薪,还有...

从大学步入社会,每个人都会面临角色和身份的转变,大部分同学对此充满信心和期待,仿佛有用不完的精力、耗不尽的热情。可是社会中的磨砺也让心态慢慢变得成熟,生活、文化等方面的落差显现出来,想要做出改变,…

java项目-第151期ssm文物管理系统_java毕业设计_计算机毕业设计

java项目-第151期ssm文物管理系统_java毕业设计_计算机毕业设计 【源码请到资源专栏下载】 今天分享的项目是《ssm文物管理系统》 该项目分为2个角色,管理员、用户。 用户可以浏览前台文物信息、论坛交流、文物资讯、留言反馈。 管理员负责登录后台系统&#xff0c…

[附源码]java毕业设计校医院病人跟踪治疗信息管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

产品质量模型

产品质量模型将系统/软件产品质量属性划分为8个特征:功能性、性能效率、兼容性、易用性、可靠性、安全性、可维护性、可移植性,每个特征由一组相关子特征组成。 衡量一个优秀软件的维度: 产品质量模型只应用于软件产品,或者包含软…

从零开始做一款Unity3D游戏<三>——编写游戏机制

添加跳跃 了解枚举 使用层遮罩 发射投射物 实例化对象 管理游戏对象的创建 游戏管理器 维护玩家属性 get和set属性 精益求精 图形用户界面 胜败条件 使用预编译指定和命令空间 总结 前面一章,我们专注于通过代码来移动玩家和相机,同时了解了…

深入理解计算机系统——Midterm Exam 2012

深入理解计算机系统——Midterm Exam 2012Problem 4 疑问Problem 6 疑问Problem 7 疑问Problem 8 疑问试卷&#xff1a;Midterm Exam 2012 答案&#xff1a;Exam Solutions Problem 4 疑问 第 4 题为第三章内容&#xff0c;这里觉得题目有一步骤写错了&#xff0c;<13> …

让Python可视化事半功倍!

分享一款不错的Matplotlib可视化查询手册&#xff0c;让Python Matplotlib事半功倍&#xff01; 当可视化时&#xff0c;记不清楚图形Marker名称、colormap名称、坐标轴刻度设置、图例设置等等时&#xff0c;稍微扫描一眼该手册&#xff0c;直接YYDS。 下面简单介绍一下这个手册…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.5 变更缓存供应商 Ehcache

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.5 变更缓存供应商 Ehcache5.5.1 缓存实现方案5.5.…

部署支持使用Redis哨兵模式,支持纳管ClickHouse数据库,JumpServer堡垒机v2.28.0发布

2022年11月21日&#xff0c;JumpServer开源堡垒机正式发布v2.28.0版本。在这一版本中&#xff0c;JumpServer的部署支持使用Redis哨兵集群作为后端缓存数据库&#xff0c;从而使系统更加健壮和高可用。操作日志审计方面&#xff0c;新增支持查看资源变更信息。当资源有新增、更…

今天给大家介绍一篇基基于SSM超市管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

【迁移学习】分布差异的度量以及迁移学习的统一表征方法

在文本分类中&#xff0c;由于文本数据有其领域特殊性&#xff0c;因此&#xff0c;在一个领域上训练的分类器&#xff0c;不能直接拿来作用到另一个领域上&#xff0c;这就需要用到迁移学习。 迁移学习是机器学习中重要的研究领域&#xff0c;ICML、NIPS、AAAI、ICIR等国际人工…

号码认证平台有哪些?号码认证平台费用?

随着互联网的发展&#xff0c;电话经常接到骚扰电话、买房、保险等电话&#xff0c;让用户不胜其扰。目前提供电话标记的软件个数达到几十款之多&#xff0c;可以有效预防诈骗发生&#xff0c;也暴露出“号码标记随意性强”“错误标记取消难”等一系列问题。如果被恶意标记&…

Rancher 全球化部署最佳实践

作者 万绍远&#xff0c;CNCF 基金会官方认证 Kubernetes CKA&CKS 工程师&#xff0c;云原生解决方案架构师。对 ceph、Openstack、Kubernetes、prometheus 技术和其他云原生相关技术有较深入的研究。参与设计并实施过多个金融、保险、制造业等多个行业 IaaS 和 PaaS 平台设…