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

JAVA面试题分享三百六十:事务@Transactional失效的10种场景 日常开发中,我们经常使用Spring事务,肯定也或多或少的遇到过@Transactional失效的场景,熟悉的小伙伴可能很快的就能找到原因,但是不是很了解的小伙伴可能就要费些功夫排查原因了。那么@Transactional失效的场景都有哪些呢?本章节针对@Transactional的问题,做以下总结整理。1、同一个类中,方法内部调用事务失效2、事务方法被final、static修饰3、当前类没有被Spring管理4、非public修饰的方法(存在版本差异)5、事务多线程调用。 阅读详情
AI摘要

本文深入解析了声明式事务的概念及其实现方式,介绍了基于配置文件和注解的两种实现方法,并详细阐述了注解方式的工作原理及其在实际应用中的注意事项。

声明式事务实现方式

所谓声明式事务,也就是通过配置的方式,比如通过配置文件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才会回滚事务。当然也可以自定义回滚的异常类型。

Java事务失效的七种方式 在Java中,事务管理通常由Spring框架提供支持,通过使用@Transactional注解来声明事务。然而,在某些情况下,事务可能会失效,导致数据不一致或其他问题。以下是几种常见的Java事务失效情况及其原因和解决方法。 阅读详情

相关推荐

【spring】Spring事务失效分析,事务回滚失败原因,事务的传播机制

1.第一种情况 :调用方加上@Transactional 注解,被调用方未加上注解 (同一个service类) Exp: @Transactional void methodA(){ // insert table1 methodB(Object obj); } void methodB(){ // insert table2 } 结论:methodB()出现异常,抛给methodA,A中捕获到异常,进行回滚处理,table1,table2都未插入 2.第二种情况:调用方未加上注解,被调用方加上注解(同

孟秋与你的博客 5845

内部方法调用,事务不起作用的原因及解决办法

在做业务开发时,遇到了一个事务不起作用的问题。事情是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚。查阅资料后,问题得到解决,记录下来分享给大家。 场景 我在这里模拟一个场景,大概的调用方式就如下面的代码这样。 @Override @Transactional(rollbackFor = RuntimeException.class) public ...

平头哥的技术博文 7648

【学习体会】Lighttools8.4.0:简单光学系统实例

添加球型光源(SphereSource)和表面接收器: 对光线模拟的参数进行设置: 光线追踪-模拟输入 要追踪的光线总数,决定模拟的准确度,总数越多,准确度越高,当然耗时更多 预览光线数量是模拟之后可以看到的示意光线(黑线),一般是100~1000,随意设置 点击,开始模拟: (模拟结果) 如果光线太多,则会出现,可以看到剩余时间 照度分析: 分析-照度显示-光栅图表 ...

LeonJin的博客 1万+

内部调用事务失效原因

大家都知道在事务里面如果发生了内部调用那么事务会失效,具体的原因是因为事务的根本还是aop也就是动态代理,那么如果是类里面自己调用的话是不会使用代理对象去调用的而是使用普通类,举个例子: public class O{ public void a(){ // 进入a方法 A方法 ....... // 方法内部调用,不是代理对象不触发aop b(); } public void b(){ B方法 ....... } } //代理对象 O o = new O(); $pro.

weixin_47733858的博客 1675

工业焊缝缺陷检测实战:我用PatchCore在自建数据集上踩过的那些坑

本文详细介绍了PatchCore算法在工业焊缝缺陷检测中的实战应用,包括数据准备、模型调参和阈值优化等关键环节。通过分析焊缝图像的特殊性和anomaly detection技术的优化策略,分享了在自建数据集上提升检测精度的实用经验,为工业质检领域提供有价值的参考方案。

weixin_42624889的博客 397

OpenVins解析:基于滤波框架的SLAM

这一方式存在的关键问题是匹配耗时很长,对性能影响显著。可以参考ORBSLAM3中的匹配方式来对其优化,比如左右目匹配可以在极线上搜索,前后帧可以利用运动先验投影匹配。理论上加入路标点会提升精度,代价是增加了计算量。着重说下基于描述子的匹配:OpenVins中匹配的方式是robust_match(),里面是调用的opencv的。openvins中不仅仅进行了传统的MSCKF更新(状态向量中不包含路标点),还在。中进行了包含路标点的估计更新。图像帧到来时,利用IMU递推得到的位姿给该图像帧赋初值。

qq_18076309的博客 4073

同一个类的不同方法,A方法没有@Transactional,B方法有@Transactional,A调用B方法,事务不起作用

问题: 同一个类的不同方法,A方法没有@Transactional,B方法有@Transactional,A调用B方法,事务不起作用 原理解析: spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。 此时,当这个有注解的方法被调用的时候,实际上是由代...

装睡的小5郎的博客 1万+

瑞芯微RK3506开发板Ethercat主站性能优化实战:从内核配置到微秒级延迟控制

本文详细介绍了在瑞芯微RK3506开发板上实现EtherCAT主站微秒级延迟控制的实战优化方案。核心在于部署Preempt-RT实时内核,并进行深度系统调优,包括CPU隔离、中断亲和性设置、内存锁定及电源管理调整。通过绕过Linux网络栈的专用驱动加载与配置,最终实现了稳定的高性能实时控制,满足工业自动化需求。

tcp8optimizer的博客 315

Spring事务调用类自己方法失效解决办法和原因

问题 正常情况下,我们都是在controller里调用service里的方法,这个方法如果需要加事务,就在方法上加上@Transactional,这样是没问题的,事务会生效。 可是如果像下面这样,绕以下,service里方法调用了自己类的方法,这个时候即使加了@Transactional,事务也不会生效。 @Controller public class TestController { @Autowired private TestService testService;

北海刘德华的博客 2898

别再死记硬背参数了!用ADS手把手教你仿真一个4GHz镜像抑制混频器(附完整工程文件)

本文详细解析了4GHz镜像抑制混频器的ADS仿真全流程,从理论到实践,涵盖混频器设计基础、ADS工程搭建、二极管选型、非线性仿真及性能优化。通过实战案例,帮助工程师掌握关键参数平衡与调试技巧,提升射频电路设计效率。

weixin_42552716的博客 338

Docker入门教程:在腾讯云轻量服务器上部署你的第一个容器化应用 (2025)

还在为“在我电脑上明明是好的”而烦恼?本篇Docker入门教程,用通俗易懂的比喻解释镜像、容器的核心概念,并手把手带你在腾讯云轻量服务器上,从运行Nginx到编写Dockerfile打包自己的Python应用,轻松掌握容器化部署。

Clownseven的博客 2084

同类调用导致的@Transactional失效

我们在a()中通过this调用b()方法,不是通过代理来调用的,this指向目标对象,因此调用this.b()将不会执行b事务切面,但是a()却是通过代理模式来做的,所以只对a方法进行了事务增强,没有对b方法进行增强。注意这里并不是因为代理对象生效,而是 Spring 会认为 a() 和 b() 依然是在事务的上下文中执行(由事务的传播性),所以testMerge()是认为事务生效的,但不建议这样写的。不会,a的事务会生效,b中不会有事务,因为a中调用b属于内部调用,没有通过代理,所以不会有事务产生。

m0_64132144的博客 1182

如何在SendWS实现WhatsApp批量群发设置管理?WhatsApp群发超链有什么好处?

WhatsApp群发顾名思义就是对WhatsApp上的用户好友进行群发消息,给他们群发想要发送的消息。及时不认识对方也可以对他进行群发超链。越来越多做跨境出海运营的工作者利用WhatsApp进行营销推广,因为他能做到低成本高回报,向客户发送消息曝光自己的品牌或产品,使得更多人了解,拓展新客户,提高成交率。

SendWS-WS云控群控拓客聊天翻译 1169

终于搞懂Spring的事务传播行为了,事务失效及传播行为的误区

误区一 和同事讨论下面情况会不会事务失效,答案是不会,但是网上很多文章说会失效,把我误导了很长一段时间; 但是异步调用失效了,答案也跟网上说的一样,这样的调用addTenant()方法没有被增强代理,所以失效,为什么事务没失效呢? @Transactional(rollbackFor = Exception.class) public void addUser(User user) { userMapper.updateById(user); addTenan

weixin_47534571的博客 438

PX4从放弃到精通(五):PX4中的姿态表示方法及转换关系

文章目录机体坐标系与地理坐标系一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 机体坐标系与地理坐标系 在实际应用中,加速度计的测量轴是由运动平台安装固定此器件的轴向决定的。这些坐标轴就形成了载体坐标系,定义如下: 坐标原点设在载体质心(这样可简化运动方程的推导); y轴指向载体前方,称为横滚轴,横滚角以y轴为起始旋转轴而得到,符合右手定则; x轴与y轴夹角90°,指向载体横向,称为俯仰轴,俯仰角以x轴为起始旋转轴而得到,符合右手定则; z轴与x轴、y轴构成右手笛卡儿坐标系,指向载体垂直方向

超维空间科技的博客 8112

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

spring事务失效原因及解决方案

1. 需求示例 需求伪代码如下: @Service public class JysdService { public String test1(args) { try { test2(args); } catch (Exception e) { return "异常"; } .... } @Transactional(rollbackFor = Exceptio

乙壳虫的博客 1万+

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

spring中try catch中的方法添加事务失效

由于业务场景,需要在try 中调用业务方法,业务方法上添加事务注解: @Transactional(rollbackFor = Exception.class) public void handleRepayRecordMessage(List<TmpRepayRecord> unDealtRepayRecordList) { for (TmpRepayRecord tmpRepayRecord : unDealtRepayRecordList) { try {

weixin_41761540的博客 1297

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Spring AOP无法调用自身方法的原因

1、问题概述 在使用Spring AOP时,或多或少会碰到一些方法无法被增强的问题,有时同一个类里面的方法有的可以被增强,有的却无法被增强。要分析原因,首先要从Spring AOP的实现机制入手。 Aop底层实现有两种方法:  1、基于JDK动态代理,通过接口来实现方法拦截,所以必须要确保要拦截的目标方法在接口中有定义,否则将无法实现拦截  2、GCLib动态代理,通过动态生成子类来实现方法拦...

实践是最好的方法 2676

@Transactional注解同一个类里方法互相调用注解失效问题

问题:同一个类中一个不加注解的方法调用另一个加注解的方法,注解失效 第一个图调用第二个图的方法 打印日志注解失效 解决办法: 添加以下代码 import org.springframework.aop.framework.AopContext; //同一类中调用事务方法,需要重新获取代理类,否则被调用方法是由原始类调用,事务失效 saleServiceImpl proxySaleService = (saleServiceImpl) AopContext.currentPro...

y_0927的博客 683

Spring AOP嵌套调用,同一类的方法调用切面切不到,@Transactional同一个类不生效问题(含解决办法)

Spring AOP嵌套调用,同一类的方法调用切面切不到,@Transactional同一个类不生效问题(含解决办法)

weixin_45807440的博客 3212

事务@Transactional失效的10种场景

日常开发中,我们经常使用Spring事务,肯定也或多或少的遇到过@Transactional失效的场景,熟悉的小伙伴可能很快的就能找到原因,但是不是很了解的小伙伴可能就要费些功夫排查原因了。那么@Transactional失效的场景都有哪些呢?本章节针对@Transactional的问题,做以下总结整理。1、同一个类中,方法内部调用事务失效2、事务方法被final、static修饰3、当前类没有被Spring管理4、非public修饰的方法(存在版本差异)5、事务多线程调用。

竹林幽深 1962

spring事务失效场景三:内部方法调用

这篇笔记主要记录spring事务失效场景三:在同一个类中,用非事务方法调用事务方法 首先,这种场景,失效的原因是,在非事务方法中,调用同一个类的事务方法,和动态代理没有关系,事务拦截器无法拦截到,就是一个this方法调用,所以,在实际业务开发过程中,一定要避免这种场景 应用 应用其实简单 ...

小小少年的博客 1294

spring中加注解方法被同一个类内部方法调用导致AOP失效的解决方案(如@Transactional失效)

现象 示例: public class A { //...... @Transactional public void serviceA() { ...... } public void serviceB() { ...... serviceA() ...... } } 大概多数人都会遇到这么一个坑,如果使用spring的@Transactional给A类中的某个业务方法servi

evasnowind的专栏 1954

Spring事务失效 -方法内部调用

文章 添加链接描述https://www.cnblogs.com/heqiyoujing/p/11221093.html

炫的博客 2万+

Spring同一个Service类非事务方法调用事务方法事务失效解决方案

今天看到线上异常,根据异常排查了相关落库存储的数据,然后进而排查相关业务Service中逻辑代码,事务方法中对A、B、C三张表调用其相关Service依次插入记录。但是B插入失败,A表插入记录并没有事务回滚。然后排查了一下业务代码逻辑,发现在一个Service中,一个非事务方法调用事务方法导致的事务并没有生效导致的。

秋夜无霜 5776

spring事务@Transactional在同一个类中的方法调用不生效

参考: https://www.jianshu.com/p/2e4e1007edf2 https://blog.youkuaiyun.com/ligeforrent/article/details/79996797 问题 也可以描述为 同一个类中,只有方法加了 @Transactional 事务为什么不生效? 类上加事务,方法不加事务,事务是生效的! 类上加事务,方法也加事务,事务是生效的!   ...

改变ing 2万+
上一篇: 优快云不用登录也可以复制代码,解决登录后才能复制的办法
下一篇: 无须关注看文章
不平衡的叉叉树
博客等级 码龄7年 5833粉丝 181原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值