Spring事务失效,同一个类中的内部方法调用事务失效

这篇具有很好参考价值的文章主要介绍了Spring事务失效,同一个类中的内部方法调用事务失效。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

声明式事务实现方式

所谓声明式事务,也就是通过配置的方式,比如通过配置文件xml或者注解的方式,来告诉Spring哪些方法需要Spring帮忙管理事务,然后开发者只需要关注业务代码,而事务的事情则由Spring自动帮我们控制。

配置文件的方式:即在spring.xml文件中进行统一配置,开发者基本不用关注事务的事情了,一切交给spring处理。

基于注解的方式:只需要在想要添加事务的方法上加上@Transaction注解就可以了。

实际工作中,基于配置文件的方式用的很少,我们工作中主要还是用注解的方式较多。

注解方式实现原理

简单介绍一下原理

当spring容器启动的时候,发现有@EnableTransactionManagement注解,此时会拦截所有bean的创建,然后会扫描一下bean上是否有@Transaction注解(类、接口、或者方法上有这个注解都可以),如果有这个注解,spring会通过aop的方式给这个bean生成代理对象(代理对象中存在本类对象),代理对象中会增加一个拦截器,拦截器会拦截bean中public方法的执行,会在方法执行前启动事务,方法执行完毕之后提交或者回滚事务。

同一个Service类中,方法B上有事务注解,方法A上没有,在A中调用B方法,事务会失效

其实仔细看了上面的原理,也就很好解释了为什么会失效了。

首先,外部调用A方法时,是通过代理对象来调用的,如ProxyService.A(),而我们在A方法中调用B方法是通过本类对象Service来实现的,即Service.B(),因为代理对象中存在Service对象。所以这就会导致事务失效。

@Service
class A{
    @Transactinal
    method b(){...}
    
    method a(){    //标记1
        b();
    }
}
 
//Spring扫描注解后,创建了另外一个代理类,并为有注解的方法插入一个startTransaction()方法:
class proxy$A{
    A objectA = new A();
    method b(){    //标记2
        startTransaction();
        objectA.b();
    }
 
    method a(){    //标记3
        objectA.a();    //由于a()没有注解,所以不会启动transaction,而是直接调用A的实例的a()方法
    }
}

当我们调用A的bean的a()方法的时候,也是被proxy$A拦截,执行proxy$A.a()(标记3),然而,由以上代码可知,这时候它调用的是objectA.a(),也就是由原来的bean来调用a()方法了,所以代码跑到了“标记1”。由此可见,“标记2”并没有被执行到,所以startTransaction()方法也没有运行。

必须通过代理对象来调用方法,事务才会生效。

注意代理对象最终都是要调用原始对象的,而原始对象去调用方法时,是不会再触发代理了。

方法A调用方法B事务失效分析

如果A和B两个方法在同一个类中

1、如果A加了@Transaction注解,B上有没有@Transaction注解,事务都是有效的,则AB在同一个事务中。

2、如果A不加@Transaction注解,B上有没有@Transaction注解,事务都是无效的

如果A和B两个方法不在同一个类中

1、如果A加了@Transaction注解,B上有没有@Transaction注解,事务都是有效的。

2、如果A不加@Transaction注解,B加了@Transaction注解,只有B是有事务的。

3、如果A不加@Transaction注解,B也不加@Transaction注解,A和B都是没有事务的。

简单理解:

只要A加了@Transaction注解,那么无论是不是在同一个类中,无论B加不加注解,AB都在同一个事务中。

A不加注解,B加了注解,如果AB在同一个类中,则事务失效;如果AB不同类,则只有B有事务

原因分析:在A方法有@Transaction注解时,spring在管理的时候会生成一个代理类,在外部调用A方法时,实际执行的是代理类里面的方法,该代理类里面的方法已经包括了B方法的调用,已经成为了一个方法,所以事务是有效的。

事务失效的常见情况

1、方法不是public类型的

@Transaction注解可以用在类、接口和方法上,如果将@Transaction注解用在了非public方法上,事务将失效

因为spring事务底层是通过cglib动态代理来实现的,而cglib动态代理是基于父子类来实现的,我们知道,子类是不能重载父类的private方法的,所以在private方法上面加@Transaction会导致事务失效。

2、向上述所说的方法调用场景

3、异常类型错误

spring事务的回滚机制:对业务方法进行try-catch,如果捕获到有指定的异常时,spring会自动对事务进行回滚。

那么问题来了,哪些异常会让spring自动回滚事务呢?并不是任何异常情况下,spring都会回滚事务的,默认情况下,RuntimeException和Error异常情况下,spring才会回滚事务。当然也可以自定义回滚的异常类型。文章来源地址https://www.toymoban.com/news/detail-416871.html

到了这里,关于Spring事务失效,同一个类中的内部方法调用事务失效的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring事务失效场景之类内部方法调用及解决方案

    在日常开发中,经常有需要使用事务来保证数据一致性的情况。简单点的话直接在方法上面加@Transactional注解就可以了。 但这样存在一个问题,在整个业务方法层面加注解会把很多并不需要归入事务的操作也归入到了事务里面,这样会可能会出现大事务的情况,影响系统性能

    2024年01月17日
    浏览(47)
  • Python 调用同一文件夹下另一个.py文件中的类和函数

    A.py文件如下: 在B.py文件调用A.py文件的add函数如下: 输出结果为: A.py文件如下: 在B.py文件调用A.py文件的add函数如下: 得到结果: 参考链接 python调用另一个.py文件中的类和函数或直接运行另一个.py文件

    2024年02月13日
    浏览(61)
  • 同一个请求同一个参数,postman发送成功,jmeter失败

    当使用jmeter 请求时吗,注意请求参数中是否包含中文。 问题来由: 1.先用postman发送,成功。  2.一模一样,header一样,请求一样,但是就是一直查询不出来。 3.经过fiddler抓包,再次对比请求头,请求体,还是没有发现有什么差别。 4.猜想: 此接口其他参数传送,都没有问题

    2024年02月13日
    浏览(55)
  • C++笔记之设计模式全局状态管理类:使整个工程项目中的所有函数可以访问同一个变量,并且能够感知到这个变量的变化(变量共享)

    —— 杭州 2024-03-21 夜 实现方法 : 全局变量(不介绍) 单例模式 全局状态管理类 全局状态管理类+单例模式 静态变量或静态成员(不介绍) code review!

    2024年03月22日
    浏览(65)
  • Spring中事务失效的8中场景 对于一个事务开子线程

    1. 数据库引擎不支持事务 这里以 MySQL为例,MyISAM引擎是不支持事务操作的,一般要支持事务都会使用InnoDB引擎,根据MySQL 的官方文档说明,从MySQL 5.5.5 开始的默认存储引擎是 InnoDB,之前默认的都是 MyISAM,所以这一点要值得注意,如果底层引擎不支持事务,那么再怎么设置也

    2024年02月16日
    浏览(39)
  • 多个硬盘挂载到同一个目录

    同一目录无法重复挂载,后挂载的会覆盖之前挂载的磁盘。但是现在需要将4块磁盘并行挂载,该如何操作呢? 将2块磁盘合并到一个逻辑卷 进行挂载。 基本知识 基本概念PV(Physical Volume)- 物理卷物理卷在逻辑卷管理中处于最底层,它可以是实际物理硬盘上的分区,也可以是整

    2024年02月08日
    浏览(83)
  • CSS 沿着同一个方向旋转

    主要解决旋转360°后倒转的问题,沿着一个方向旋转,而不是倒回去重新开始。 效果  源码 在线示例 同方向旋转

    2024年02月15日
    浏览(50)
  • 【点击新增一个下拉框 与前一个内容一样 但不能选同一个值】

    主要是看下拉选择el-option的disabled,注意不要混淆 methods:

    2024年02月11日
    浏览(60)
  • 如何将微前端项目部署在同一台服务器同一个端口下

    作者:京东科技 高飞 本文旨在通过部署微前端项目的实践过程中沉淀出一套部署方案,现就一些重点步骤、碰到的问题做了一些总结。 因为线上部署主应用时需要用到子应用的线上可访问地址,因此部署顺序应该是先部署子应用,保证子应用能够线上可访问后,再将子应用

    2023年04月11日
    浏览(57)
  • 不同设备使用同一个Git账号

    想要在公司和家里的电脑上用同一个git账号来pull, push代码 第1种方法, 依次输入 第2种方法, 输入 用户名和邮箱与原设备保持一致 输入上面三句话之后会弹出提示是否在此电脑上创建.ssh文件夹,回车同意即可 接着会提示设置密码,不设置就连按两次回车 完成之后,在 “

    2024年04月10日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包