Spring事务失效场景?

题目详细答案

Spring事务失效的场景主要有以下几种。

非public方法使用@Transactional

场景描述:Spring事务管理是基于AOP实现的,而AOP对于JDK动态代理CGLib动态代理只会代理public方法。如果事务方法的访问修饰符为非public,SpringAOP无法正确地代理该方法,从而导致事务失效。

示例代码:事务方法的访问修饰符被设置为private、default或protected。

解决方案:将需要事务管理的方法设置为public。

在同类中的非事务方法调用事务方法

场景描述:Spring的事务管理是通过动态代理实现的,只有通过代理对象调用的方法才能享受到Spring的事务管理。如果在同一个类中,一个没有标记为@Transactional的方法内部调用了一个标记为@Transactional的方法,那么事务是不会起作用的。

解决方案:尽量将事务方法放在不同的类中,或者使用Spring的AopContext.currentProxy()来获取当前类的代理对象,然后通过代理对象调用事务方法。

事务传播级别属性设置不当

场景描述:在Spring的事务管理中,如果在一个支持当前事务的方法(比如,已经被标记为@Transactional的方法)中调用了一个需要新事务的方法,如果后者方法抛出了异常,但异常并未被Spring识别为需要回滚事务的异常,那么后者的事务将不会回滚。

异常类型不匹配

场景描述:默认情况下,Spring只有在方法抛出运行时异常或者错误时才会回滚事务。对于检查性异常,即使你在方法中抛出了,Spring也不会回滚事务,除非你在@Transactional注解中显式地指定需要回滚哪些检查性异常。

解决方案:了解Spring事务管理对异常的处理,必要时在@Transactional注解中指定需要回滚的异常类型。

事务拦截器配置错误

场景描述:如果没有正确地配置事务拦截器,例如没有指定切入点或指定了错误的切入点,就会导致Spring事务失效。

@EnableTransactionManagement
@Configuration
public class TxConfig {@Beanpublic Advisor transactionAdvisor() {AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression("execution(* com..service.*.*(..))"); // 包路径错误return new DefaultPointcutAdvisor(pointcut, transactionInterceptor());}
}

事务超时配置错误

场景描述:如果事务超时时间设置得太短,就有可能在事务执行过程中出现超时,从而导致Spring事务失效。

Spring事务超时是通过JDBC的java.sql.Connection#setNetworkTimeout()实现的,底层流程:

if (System.currentTimeMillis() - startTime > timeoutMillis) {throw new TransactionTimedOutException("Transaction timed out");
}

Spring事务失效场景深度解析

一、非public方法失效的本质原因

底层机制

  1. 代理生成限制
// Spring源码中的判断逻辑
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null; // 直接返回不创建事务属性
}
    • JDK动态代理只能代理接口中的public方法
    • CGLIB虽然能代理类方法,但Spring主动限制了非public方法的事务支持
  1. 设计考量
    • 非public方法通常被视为内部实现细节
    • 保持事务边界清晰(public方法才是服务契约)

典型错误示例

@Service
public class PaymentService {@Transactionalprotected void processPayment() {  // protected方法// 事务不会生效!}
}

二、同类调用失效的代理机制

核心问题图解

[客户端] --> [Spring代理对象] --> [真实对象]调用createOrder()       this.validate()绕过代理

字节码层面分析

  1. 代理对象生成后,方法调用流程:
    • 外部调用:proxy.createOrder()
    • 内部调用:realObject.validate()(直接调用,不走代理)

解决方案对比

方案

优点

缺点

拆分类

符合单一职责原则

增加类数量

自注入

改动最小

存在循环依赖风险

AopContext.currentProxy()

灵活

需配置exposeProxy=true

三、传播行为配置陷阱

REQUIRES_NEW的隔离性

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void auditLog() {// 即使外层事务回滚,此操作仍会提交// 但会创建新连接,可能耗尽连接池
}

NESTED的数据库支持

  • 支持:MySQL、PostgreSQL
  • 部分支持:Oracle(行为差异)
  • 不支持:MyISAM引擎

四、异常处理不当的判定逻辑

Spring回滚决策树

  1. 检查rollbackFor/noRollbackFor明确指定的异常
  2. 默认规则:
    • RuntimeException及其子类 → 回滚
    • Error及其子类 → 回滚
    • 检查型异常(Exception) → 提交

易错场景示例

@Transactional
public void importData() throws IOException {try {parseFile(); // 可能抛出IOException} catch (IOException e) {throw new BusinessException(e); // 必须转换为RuntimeException}
}

五、数据库引擎关键影响

事务支持矩阵

引擎特性

InnoDB

MyISAM

Memory

事务支持

✔️

✖️

✖️

行级锁

✔️

✖️

✖️

外键支持

✔️

✖️

✖️

检查方法

SHOW TABLE STATUS WHERE Name='table_name';

六、静态/最终方法限制

JVM方法调用机制

  • final方法:静态绑定,编译期确定调用目标
  • static方法:类级别调用,与对象实例无关
  • 二者都无法被动态代理拦截

事务调试四步法

  1. 检查代理类型
System.out.println(service.getClass().getName());
// 应输出包含$$EnhancerBySpringCGLIB$$或$Proxy的类名
  1. 验证事务状态
TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.getCurrentTransactionName();
  1. 开启事务日志
logging.level.org.springframework.transaction.interceptor=TRACE
logging.level.org.springframework.jdbc=DEBUG
  1. 数据库监控
SHOW ENGINE INNODB STATUS;  -- MySQL
SELECT * FROM V$TRANSACTION; -- Oracle

最佳实践清单

  1. 编码规范
    • 所有事务方法必须为public
    • 避免在事务方法中捕获所有异常
    • 显式指定rollbackFor
  1. 配置检查
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class TxConfig {@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dataSource());}
}
  1. 测试验证
@Test
@Transactional
public void testWithRollback() {// 测试后自动回滚assertThrows(Exception.class, () -> service.method());
}

理解这些原理后,可以系统性地避免事务失效问题,而不仅是记住表面现象。实际开发中建议结合日志监控和单元测试,确保事务行为符合预期。

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

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

相关文章

1.电动汽车动力电池系统技术介绍与分类

1.电动汽车动力电池系统技术介绍与分类 1.1 电动汽车发展的三个 “黄金时代” 第一个黄金时代(19 世纪末 - 20 世纪初) 技术基础:铅酸蓄电池发明(1859 年),推动电动三轮车(1873 年)、…

调用阿里云-阿里云百炼 AI

相关文档:大模型服务平台百炼控制台 多轮对话:通义千问模型的多轮对话_大模型服务平台百炼(Model Studio)-阿里云帮助中心 创建知识库:大模型服务平台百炼控制台 创建智能体:大模型服务平台百炼控制台 点击智能体发布后&#x…

Apache Flink:从实时数据分析到实时AI

引言欢迎踏上这段深入了解 Apache Flink 演进历程的旅程,Apache Flink 是一项重新定义了实时数据处理的技术。本博客文章基于王峰(阿里云开放数据平台负责人、Apache Flink Committer)在 2025 年 Flink Forward Asia 新加坡大会上的演讲内容编…

oelove奥壹新版v11.7旗舰版婚恋系统微信原生小程序源码上架容易遇到的几个坑,避免遗漏参数白屏显示等问题

oelove和 金媒我都用过一段时间,其中oelove 用的时间较多,也比较了解这个系统,这个系统比较不错的就是小程序是原生的(完全遵循微信开发者平台规则非Uniapp)开发的,原生小程序的特点就是兼容性好&#xff0…

行为模式-模板方法模式

定义:Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithms structure.(定义一个操作中的算法的框架&a…

Java集合遍历练习题

以下是10道难度递增的集合遍历练习题,涵盖List、Set、Map的各种遍历方式,包含解题思路、代码实现和输出结果: 练习题1:基础遍历 - ArrayList的for-each遍历 题目:创建一个存储5个字符串的ArrayList(元素为&…

深度学习·ZegclipClip-RC

Zegclip 获取图像的特殊编码:使用prompt tuning的技术,目的是减少过拟合和计算量。调整文本编码:使用RD关系描述符,将每一个文本对应的[cls] token和图像对应的[cls] token作哈密顿积,最后文本[cls]token形式化任务 文…

Taro 扩展 API 深度解析与实战指南

Taro 扩展 API 深度解析与实战指南 Taro 作为一款优秀的多端开发框架,提供了一系列强大的扩展 API,这些 API 极大地提升了开发效率和应用的可维护性。本文将深入解析 Taro 的扩展 API,并根据其功能特性进行分类讲解,帮助开发者更…

容器之王--Docker的部署及基本操作演练

1.2 部署docker 1.2.1 容器工作方法1.2.2 部署第一个容器 官方站点:https://docs.docker.com/ 1.2.2.1 配置软件仓库 ]# cd /etc/yum.repos.d ]# vim docker.repo [docker] name docker-ce baseurl https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/sta…

VFTO与局部放电-高压设备绝缘系统的双重挑战与防护策略

目录 引言VFTO的定义与形成机理VFTO对高压设备绝缘系统的影响局部放电的危害与机制VFTO与局部放电的关联性分析检测与监测技术防护与抑制措施未来技术发展趋势结论与展望引言 在现代电力系统中,超快速暂态过电压(Very Fast Transient Overvoltage, VFTO&…

Windows下Rust编码实现MP4点播服务器

Rust编码可以实现众多简洁、可靠、高效的应用,但语法逻辑要求严格,尤其是依赖库的选择调用,需要耐心坚持“推敲”。借助DeepSeek并反复编程调试和问答改进,可以最终得到完整有效的Rust编码。下面分享Windows下Rust编码实现MP4点播…

ubuntu-相关指令

1、串口1.1确认在系统中检查设备是否正常加载,在终端输入以下命令:way1:ll /dev | grep ttyUSB(ll是LL的小写) way2:ll /dev | grep ttyACM way3:ll /dev | grep ttyCH343USB&#…

docker容器临时文件去除,服务器容量空间

概述: 接到告警提醒,服务器容量不足,去查看了一下,发现确实100g左右容量已基本用完;分析: 1)查看根目录下哪些文件夹占用容量较大 使用命令“ du -ah --max-depth1 / ” 查看目标目录下所有文件…

损耗对信号质量的影响

损耗通常分为介质损耗与导体损耗:介质损耗:介质被施加电场后介质内部带电粒子在外加电场的作用力下进行微小移动介质损耗与频率成正比导体损耗:导体由于存在电阻,在有电流流过时产生的热量造成的损耗为导体损耗。同时,…

【42】【OpenCV C++】 计算图像某一列像素方差 或 某一行像素的方差;

文章目录1 要使用到的函数 和 原理1.1 cv::meanStdDev 函数详解——计算均值和标准差1 .2 方差的通俗解释2 代码实现3 问题3.1 入口参数const cv::Mat& img 和 const cv::Mat img区别项目要求:C OPenCV 中 图像img ,当 string ROIdirection “H”时,…

元图 CAD 插件化革命:突破效率瓶颈,重构智能协作新范式

在建筑、机械、机电等工程领域,传统CAD软件的功能固化与场景割裂已成为效率提升的瓶颈。设计师常面临“通用工具难适配专业需求”、“跨平台协作效率低下”、“数据孤岛阻碍创新”等痛点。元图CAD凭借“场景插件化“核心技术,以模块化能力突破行业桎梏&a…

T:归并排序

归并排序.逆序对简介.归并排序.习题.逆序对简介 \;\;\;\;\;\;\;\;简单介绍一下归并排序的原理&#xff0c;逆序对的基本概念&#xff0c;然后收集相关的练习。 直接用一个基础问题来引入。 因此知道了: \;\;\;\;\;\;\;\;逆序对就是一对数满足 i<j&&nums[i]>nu…

三极管三种基本放大电路:共射、共集、共基放大电路

文章目录一、共集放大电路1.静态分析2.动态分析二、共基放大电路1.静态分析2.动态分析总结如何判断共射、共集、共基放大电路&#xff1f; 电路的输入回路与输出回路以发射极为公共端的电路称为共射放大电路。 电路的输入回路与输出回路以集电极为公共端的电路称为共集放大电路…

Function AI 助力用户自主开发 MCP 服务,一键上云高效部署

作者&#xff1a;靖苏 在 AI 与云原生协同创新的浪潮下&#xff0c;多模型、多场景智能应用日益普及。开发者面临的首要挑战&#xff0c;是如何实现模型之间、服务之间的高效协同&#xff0c;以及如何便捷地将自主研发能力拓展到云端&#xff0c;形成灵活可扩展的智能服务。MC…

c++编译环境安装(gcc、cmake)

一、gcc下载 下载地址&#xff1a;https://ftp.gnu.org/gnu/gcc/ 选择想要下载的版本&#xff0c;然后解压&#xff0c;查看 contrib/download_prerequisites 中的依赖。 以我下载的 gcc-7.3.0 为例&#xff0c; 二、安装依赖包 【gmp】 https://ftp.gnu.org/gnu/gmp/ 【is…