为什么内部方法调用会导致@Transactional失效?

什么情况会导致@Transactional事务失效? 一个程序中不可能没有事务,而 Spring 中,事务的实现方式分为两种:编程式事务和声明式事务,又因为编程式事务实现相对麻烦,而声明式事务实现极其简单,所以在日常项目中,我们都会使用声明式事务 @Transactional 来实现事务。 阅读详情

在上一篇文章中,我们列举了@Transactional事务失效的几大场景。其中有一个场景是class内部方法之间的调用,如下:

    @Transactional(rollbackFor = Exception.class)
    public Long createNewUser(RegisterRequest request) {
        UserDO userDO = new UserDO();
        userDO.setLoginName(request.getLoginName());
        userDO.setLoginPwd(request.getLoginPwd());
        userDO.setCreateTime(new Date());
        userDO.setUpdateTime(new Date());
        this.save(userDO);
        //这里还可以保存userinfo扩展信息,双表操作,需要事务
        addUserInfo();
        return userDO.getId();
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void addUserInfo() {
        //.....
    }

多年经验的资深程序员都会在这个点上犯错,那这是什么原因呢?接下来我们简单地分析一下。

@Transactional 是由spring aop机制实现的,究其根本,其实是由java 动态代理机制实现的,这种实现方式要想生效,必须是外部调用,因为只有外部调用才会走代理增强的实现。addUserInfo()的调用方式相当于this.addUserInfo(),this是什么大家都知道吧,它指向的是另一个实例,根本就不是代理类。

好在spring对这种自调用也给出了解决方案,那就是自注入(Self Injection),代码如下:

    @Autowire
    private xxService xxService;

    @Transactional(rollbackFor = Exception.class)
    public Long createNewUser(RegisterRequest request) {
        UserDO userDO = new UserDO();
        userDO.setLoginName(request.getLoginName());
        userDO.setLoginPwd(request.getLoginPwd());
        userDO.setCreateTime(new Date());
        userDO.setUpdateTime(new Date());
        this.save(userDO);
      //这样就生效了
        xxService.addUserInfo();
        return userDO.getId();
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void addUserInfo() {
        //.....
    }

这种解决方案不是很优美,但是也只能这样了。这个自调用问题在Spring AOP中广泛存在,本质上是动态代理无法解决的盲区,只有AspectJ这类静态代理才能解决。

【BUG】@Transactional注解在同类方法调用中不生效 后台代码 今天做系统开发的时候,遇到了一个BUG:@Transactional注解在同类方法调用中不生效 代码如下: /** * @description: 快递100接口服务类 * @date 2021/11/23 */ @Service public class SysExpressServiceImpl implements ISysExpressService { /** * 处理快递100推送请求并响应 * @param request 快递100的推送请求 阅读详情

相关推荐

@Transactional 注解和事务的使用、失效情况

针对隔离性的强度,共有以下事务提交之后事务还没有提交能被其他的事务看到因此,有下述三个事务的隔离级别脏读不可重复读幻读不可重复读的和幻读很容易混淆,不可重复读侧重于修改幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。

учёба 2162

@Transactional失效——同一个类中方法调用导致,解决方案!

@transaction注解失效的6种场景:https://blog.youkuaiyun.com/zhangkaixuan456/article/details/108882496 同一个类中方法调用,导致@Transactional失效 开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。 .

zhangkaixuan456的博客 1万+

手把手教你用UM982搭建厘米级RTK定位系统(附避坑指南)

本文详细介绍了如何使用UM982模组搭建厘米级RTK定位系统,涵盖硬件连接、软件配置和深度优化技巧。UM982支持BDS、GPS、GLONASS和Galileo等多系统全频点信号,特别适合精准农业、无人机导航等高精度应用场景。通过实战案例和避坑指南,帮助开发者快速实现厘米级定位精度。

y7z8a的博客 1442

@Transactional注解在同一个类中的方法之间调用不生效

解决方法1: 将事务方法放到另一个类中(或者单独开启一层,取名“事务层”)进行调用,即符合了在对象之间调用的条件。 解决方法2: 获取本对象的代理对象,再进行调用。具体操作如: Spring-content.xml上下文中,增加配置:<aop:aspectj-autoproxy expose-proxy=“true”/> 在xxxServiceImpl中,用(xxxService)(AopContext.currentProxy()),获取到xxxService的代理类,再调用事务方法,

mufan0216的博客 1898

基于立创·天猛星MSPM0G3507的简易PID电机控制入门项目实战

本文详细介绍了基于立创·天猛星MSPM0G3507开发板的简易PID电机控制入门项目实战。从硬件选型、电路设计、PCB布局,到软件编程中的编码器读取、PID算法实现与调参,手把手教你完成一个带屏幕显示的电机定速与定距控制项目,是学习嵌入式开发和经典PID控制算法的绝佳实践。

weixin_42596011的博客 510

图神经网络实战(7)——图卷积网络(Graph Convolutional Network, GCN)详解与实现

图卷积网络 (Graph Convolutional Network, GCN) 架构由 Kipf 和 Welling 于 2017 年提出,其理念是创建一种适用于图的高效卷积神经网络。在本节中,我们将讨论 Vanilla GNN 架构的局限性,并详细介绍 GCN 的工作原理,通过使用 PyTorch Geometric 在 Cora 和 Facebook Page-Page 数据集上实现 GCN 来验证其性能。

盼小辉丶的博客 2万+

@Transactional类内部访问失效原因详解

Spring之所以可以对开启@Transactional的方法进行事务管理,是因为Spring为当前类生成了一个代理类,然后在执行相关方法时,会判断这个方法有没有@Transactional注解,如果有的话,则会开启一个事务。 也就是说我们首先调用的是AOP代理对象而不是目标对象,首先执行事务切面,事务切面内部通过TransactionInterceptor环绕增强进行事务的增强,即进入目标方法之前开启事务,退出目标方法时提交/回滚事务。 Spring在扫描bean的时候,如果扫描到方法上有这些注解

Ahuuua的博客 6414

使用Qt Creator自带的Qt Designer构造UI界面流程总结

在本文中,我们将总结使用Qt Creator自带的Qt Designer构造UI界面的流程。在对话框中,您可以选择一个控件的信号,然后将其连接到另一个控件的槽。例如,您可以将按钮的点击信号连接到一个槽函数,以响应按钮的点击事件。右键单击窗口设计器中的空白区域,选择适当的布局管理器,如水平布局、垂直布局或网格布局。在Qt Designer中,您可以使用各种预定义的UI控件来设计应用程序的界面。现在,您可以在应用程序的源代码中使用生成的UI界面。在您的源文件中,包含相应的头文件,然后创建一个UI界面的实例。

cl6789的博客 1394

解决:同一个类中方法调用,导致@Transactional失效(AopContext.currentProxy())

我前面有一个文章讲了当调用本类方法时,被调用方法的@Transactional注解会失效,所以建议大家用编程式事务。 Spring/SpringBoot实现编程式事务 然而今天,自己推翻我自己,分享一个怎么在调用当前类带有事务注解的方法时,还能强制使事务生效的方式。 ((YourClass) AopContext.currentProxy()).withTransactionMethod(keyword); 这种写法相当于用AOP的方式调用同类的方法,使得@Transactional注解生效。spring

怪力乌龟的博客 4752

工业激光器核心参数详解与选型实战:从理论到产线落地(五)

本文深入解析了脉冲激光加工的三大核心参数——脉宽、重复频率和脉冲能量的协同作用机制。通过公式推导和产线案例,揭示了参数设置对加工良率的关键影响:1. 脉宽决定热影响区大小,缩短脉宽可显著提升加工精度;2. 重复频率影响加工速度和热积累效应,需平衡效率与质量;3. 脉冲能量决定材料去除量,过大易导致加工缺陷。文中以ABS塑料打标、模具清洗和微孔钻孔为例,展示了参数优化如何将良率从65%提升至99%,并提供了不同应用场景的参数选型表和调试技巧,强调峰值功率比平均功率更具决定性作用。

weixin_44520581的博客 2422

基于YOLOv11的建筑图纸物体检测系统设计与实现

包含多种建筑平面图,标注了墙体、门窗等元素:CAD格式的建筑图纸数据集:专门针对建筑元素的标注数据集自定义数据集:使用LabelImg等工具自行标注的建筑图纸本文以FloorPlanDataset为基础,结合部分自定义标注数据构建混合数据集。wall (墙体)door (门)window (窗)stair (楼梯)furniture (家具)text (文字标注)dimension (尺寸标注)column (柱子)

YOLO 537

在同一类中,方法相互调用,@Transactional失效情况

在同一类中,方法相互调用,@Transactional失效情况

努力努力小张的博客 1474

vs code , 配置 claude code 插件, 默认选项 : --dangerously-skip-permission

摘要:本文介绍如何在VS Code中为Claude Code插件配置--dangerously-skip-permission参数,包含两种方法:图形界面设置(适合新手)和直接编辑settings.json(精准配置)。该参数会跳过权限检查,仅建议在本地测试环境中使用。配置后需通过命令面板验证参数是否生效,并注意安全风险,避免在生产环境使用。多参数配置时需用数组格式,不同版本插件可能键名略有差异。

AI天才研究院 5012

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

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

evasnowind的专栏 1954

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

同类调用导致的@Transactional失效

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

m0_64132144的博客 1182

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

为什么事务@Transactional会失效?

而调用类内部的 @Transactional 修饰的方法时,也是因为没有成功调用代理对象,是通过 this 来调用方法的,所以事务也失效了;上述代码在添加用户之后即使遇到了异常,程序也没有执行回滚,这是因为 @Transactional 是基于 Spring AOP 实现的,而 Spring AOP 又是基于动态代理实现的,而当调用类内部的方法时,不是通过代理对象完成的,而是通过 this 对象实现的,这样就绕过了代理对象,从而事务就失效了。如果方法在执行期间,出现了异常,那么它会自动回滚事务。

weixin_43902408的博客 1334

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

A调用B方法,@Transactional事务失效情况

本人做了各种情况的测试,结果如下: 总结: 方法A调用方法B: 1、如果只有A加@Transactional注解;则AB在同一事务中; 2、如果只有B加@Transactional注解;AB方法为同一类,事务失效;AB不同类,只有B有事务; 原理: spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个子类(即...

严老板的技术梦想博客 1万+

@Transactional 注解

@Transactional 注解相信大家并不陌生,平时开发中很常用的一个注解,它能保证方法内多个数据库操作要么同时成功、要么同时失败。使用@Transactional注解时需要注意许多的细节,不然你会发现@Transactional总是莫名其妙的就失效了。 一、事务 事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种。 1、编程式事务 是指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强。 编程式事务方式需要开发者在代码中手动的管理事务

csdnlaiyanqi的博客 5万+

事务及事务失效等@Transactional

@Transactional注解相关,事务应用的一些记录

weixin_43928050的博客 655

@Transactional 事务注解失效

在使用Spring框架时,可以有两种使用事务的方式,一种是编程式的,一种是声明式的,注解就是声明式的。

aaBen_的博客 1624

聊一聊Spring中的@Transactional注解【下】【注解失效场景】

尽管 `@Transactional` 注解在 Spring 中提供了方便的事务管理功能,我们在使用过程中却常常面临其失效的问题。事务失效可能导致意想不到的数据状态和错误,影响应用的稳定性和可靠性。本文将探讨一些常见的 `@Transactional` 失效场景

懒惰蜗牛的博客 1213

spring案例:自调用导致@Transactional事务注解失效

自调用问题:在同一个类中,直接通过this调用方法会导致事务注解失效,因为调用没有经过 Spring 的代理对象。解决方法依赖注入:通过注入自身的代理对象来调用方法。AspectJ 模式:配置 Spring 使用 AspectJ 模式进行事务管理。重构代码:将事务方法移到另一个服务类中,避免自调用。通过这些方法,可以确保注解在内部方法调用中也能正常工作。

学亮编程手记 1269

spring动态代理失效,AOP失效,事务@Transactional失效原因

事务基于@Transactional注解和AOP(动态代理)

weixin_42774617的博客 1611

导致事务@Transactional失效的5种场景

我们程序中的 @Transactional 只是给调用的数据库发送了:开始事务、提交事务、回滚事务的指令,但是如果数据库本身不支持事务,比如 MySQL 中设置了使用 MyISAM 引擎,那么它本身是不支持事务的,这种情况下,即使在程序中添加了 @Transactional 注解,那么依然不会有事务的行为,这就是巧妇也难为无米之炊吧。本文中的“失效”指的是“失去(它的)功效”,也就是当 @Transactional 不符合我们预期的结果时,我们就可以说 @Transactional 失效了。

sfaf84915的博客 332
上一篇: Java语言的基本数据类型
下一篇: 你知道@Transactional注解的失效场景吗?
Javaesandyou
博客等级 码龄5年 742粉丝 563原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值