Spring中导致事务传播失效的情况(自调用、方法访问权限、异常处理不当、传播类型选择错误等。在实际开发中,务必确保事务方法正确配置)

文章目录

  • 1. 自调用(内部调用)导致事务失效
    • 示例:
    • 解决办法:
  • 2. 事务方法不是 `public` 修饰
    • 示例:
    • 解决办法:
  • 3. 未被 Spring 管理的对象
    • 示例:
    • 解决办法:
  • 4. 异常类型不匹配导致事务回滚失败
    • 示例:
    • 解决办法:
  • 5. 传播类型使用不当
    • 示例:
    • 解决办法:
  • 6. 数据库本身不支持事务
    • 解决办法:
  • 7. 使用了不支持事务的操作
    • 解决办法:
  • 8. 事务管理器未正确配置
    • 解决办法:
  • 9. 代理模式下的事务不生效
    • 解决办法:
  • 总结

在 Spring 中,事务传播机制可以有效管理事务的传播和行为。但在某些情况下,事务传播可能会失效,导致事务没有按预期进行传播和处理。以下是常见导致事务传播失效的几种情况:

1. 自调用(内部调用)导致事务失效

这是最常见的问题之一。当一个类的非事务方法内部调用自身的事务方法时,Spring 的事务代理无法起作用。这是因为 Spring 的事务管理是基于 AOP 实现的,它通过动态代理在方法执行前后插入事务逻辑。但如果是同一个类的内部调用,Spring 无法通过代理拦截这个调用,事务不会被启动。

示例:

public class MyService {@Transactionalpublic void transactionalMethod() {// 事务逻辑}public void nonTransactionalMethod() {// 通过内部调用执行事务方法transactionalMethod();}
}

在上述代码中,如果在 nonTransactionalMethod() 中调用了 transactionalMethod()transactionalMethod() 中的事务不会生效,因为这是一个自调用,不经过 Spring 的代理机制。

解决办法:

将事务方法抽取到另一个类中,或者通过依赖注入的方式调用。

@Service
public class MyService {@Autowiredprivate MyService self;public void nonTransactionalMethod() {// 使用 self 调用,事务才能生效self.transactionalMethod();}@Transactionalpublic void transactionalMethod() {// 事务逻辑}
}

2. 事务方法不是 public 修饰

Spring 的事务管理是基于代理的,它只会对 public 方法进行代理。对于 privateprotected、或者 package-private 的方法,Spring 事务不会生效,因为代理类无法拦截对这些方法的调用。

示例:

@Transactional
private void transactionalMethod() {// 事务逻辑
}

在这种情况下,事务不会生效,因为 transactionalMethod() 不是 public 方法。

解决办法:

确保事务方法是 public 的。

@Transactional
public void transactionalMethod() {// 事务逻辑
}

3. 未被 Spring 管理的对象

只有被 Spring 容器管理的 Bean,事务代理才能起作用。如果方法是在一个非 Spring 管理的类中调用的,即使添加了 @Transactional 注解,事务也不会生效。

示例:

public class ExternalClass {@Transactionalpublic void transactionalMethod() {// 事务逻辑}
}

如果 ExternalClass 不是由 Spring 容器托管,transactionalMethod() 上的事务将不起作用。

解决办法:

确保事务相关的 Bean 是通过 Spring 管理的,即确保它们是由 Spring 容器注入的,例如通过 @Service@Component 标注的类。

4. 异常类型不匹配导致事务回滚失败

Spring 的默认事务管理策略是只在遇到 unchecked 异常(RuntimeException)Error 时回滚事务。如果方法抛出了一个 checked 异常(如 IOException),事务不会回滚。

示例:

@Transactional
public void transactionalMethod() throws Exception {// 如果抛出 checked 异常,事务不会回滚throw new Exception("Checked Exception");
}

在上述示例中,方法抛出的是一个 Exception(checked 异常),默认情况下,Spring 不会回滚事务。

解决办法:

可以通过 rollbackFor 属性明确指定哪些异常需要触发事务回滚:

@Transactional(rollbackFor = Exception.class)
public void transactionalMethod() throws Exception {// 事务会回滚throw new Exception("Checked Exception");
}

5. 传播类型使用不当

事务传播类型决定了当一个事务方法调用另一个事务方法时,事务如何传播。如果传播类型配置不当,可能导致事务行为与预期不一致,甚至事务失效。

示例:

使用 Propagation.NOT_SUPPORTEDPropagation.REQUIRES_NEW 传播类型时,如果子事务方法被配置为不支持或需要新的事务,可能会导致当前事务的逻辑与原始事务隔离,无法实现事务传播效果。

@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void nonTransactionalMethod() {// 该方法不会加入现有事务,事务逻辑不会生效
}

解决办法:

根据业务需求选择正确的传播类型,例如使用 Propagation.REQUIRED 让子方法加入当前事务。

6. 数据库本身不支持事务

并非所有数据库都支持事务操作。比如,某些 NoSQL 数据库(如 MongoDB、Cassandra)对事务的支持是有限的。如果数据库不支持事务,即使在代码中配置了事务管理,事务也不会生效。

解决办法:

确保所使用的数据库支持事务,并正确配置数据库连接。

7. 使用了不支持事务的操作

某些数据库操作或框架方法不支持事务。比如,批量操作或者直接使用 JdbcTemplate 进行大批量数据插入时,可能不会受到事务控制的影响。

解决办法:

确保使用支持事务管理的数据库操作工具,如 JPA、Hibernate,或者正确配置 JdbcTemplate

8. 事务管理器未正确配置

Spring 事务管理依赖于 PlatformTransactionManager,如果没有正确配置事务管理器,事务也不会生效。常见问题包括未正确配置数据源或没有配置事务管理器。

解决办法:

确保 PlatformTransactionManager 正确配置,并且事务管理器与数据源绑定一致。

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}

9. 代理模式下的事务不生效

Spring 使用动态代理(JDK 动态代理或 CGLIB)来实现 AOP。如果使用了 JDK 动态代理,它只对接口的方法进行代理,导致如果在实现类上直接调用方法,事务可能不生效。

解决办法:

如果没有接口,确保 @Transactional 注解的类使用的是 CGLIB 代理,而不是 JDK 代理。

@EnableTransactionManagement(proxyTargetClass = true) // 强制使用 CGLIB 代理

总结

事务失效的原因主要包括自调用、方法访问权限、异常处理不当、传播类型选择错误等。在实际开发中,务必确保事务方法正确配置,并且在调用方法时遵循 Spring AOP 的代理机制,避免事务失效。

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

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

相关文章

Flutter中使用Cookies

Cookie Cookie 是一种在用户的浏览器中存储的小型文本文件,用于保存有关用户和他们的访问信息。它们通常用于以下目的: 主要功能 会话管理:保持用户登录状态,例如识别已登录的用户。个性化设置:保存用户的偏好设置&a…

Xcode真机运行正常,打包报错

1.问题: 老项目Xcode真机运行没问题,但但打包的时候却报了以下错误: some files could not be transferred (code 23) at /AppleInternal/Library/BuildRoots/4ff29661-3588-11ef-9513-e2437461156c/Library/Caches/com.apple.xbs/Sources/r…

基于python智能推荐的丢失物品招领网站的制作,前端vue+django框架,协同过滤算法实现推荐功能

背景 基于 Python 智能推荐的丢失物品招领网站,通过前端 Vue 和后端 Django 框架的结合,为用户提供便捷、个性化的服务。该系统的核心在于实现智能推荐功能,采用协同过滤算法来提高用户体验,帮助用户更快找到合适的失物或招领信息…

爬虫日常实战

爬取美团新闻信息,此处采用两种方法实现: 注意点:因为此处的数据都是动态数据,所以一定要考虑好向下滑动数据包会更新的情况,不然就只能读取当前页即第一页数据,方法一通过更新ajax数据包网址页数&#xf…

代码随想录算法训练营第51天|101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104.建造最大岛屿

文章目录 101. 孤岛的总面积102. 沉没孤岛103. 水流问题104.建造最大岛屿 101. 孤岛的总面积 卡码网 101. 孤岛的总面积 代码随想录 from collections import deque n, m map(int, input().split())matrix []for i in range(n):matrix.append(list(map(int, input().split(…

二叉树展开为链表

二叉树展开为链表 给你二叉树的根结点 root ,请你将它展开为一个单链表: 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同…

07 实战:视频捕获

代码如下: import tkinter as tk # 导入tkinter库,用于创建图形用户界面 from tkinter import ttk, filedialog, messagebox # 导入tkinter的额外部件、文件对话框和消息框 import cv2 # 导入OpenCV库,用于图像处理 import numpy as np # 导入NumPy库,用于数值计算 from P…

Redis 数据类型Streams

目录 1 基本特性 2 主要操作命令 2.1 XADD key ID field value [field value ...] 2.2 XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...] 2.3 XRANGE key start end [COUNT count] 2.4 XREVRANGE key end start [COUNT count] 2.5 XGROUP …

文件处理新纪元:微信小程序的‘快递员’与‘整理师’

嗨,我是中二青年阿佑,今天阿佑将带领大家如何通过巧妙的文件处理功能,让用户体验从‘杂乱无章’到‘井井有条’的转变! 文章目录 微信小程序的文件处理文件上传:小程序的“快递服务”文件下载:小程序的“超…

ubuntu安装golang并设置goproxy

在Ubuntu上安装Go语言(Golang)通常有几种方法,以下是一些常见的安装步骤: 方法一:使用包管理器安装 更新包列表: sudo apt update安装Go: sudo apt install golang-go验证安装: go …

中电金信重磅发布《金融数据安全治理白皮书》

金融行业作为数据密集型行业,对数据的依赖日益加深,但数据价值的提升也带来了严峻的数据安全挑战。面对频繁的网络攻击、数据泄露事件以及日益严格的监管法规,金融机构在追求数据价值创造的同时,愈加重视数据安全问题,…

Sigrity Power SI Model Extraction模式如何提取电源网络的S参数和阻抗操作指导(一)

Sigrity Power SI Model Extraction模式如何提取电源网络的S参数和阻抗操作指导(一) Sigrity PowerSI是频域电磁场仿真工具,以下图为例介绍如果用它观测电源的网络的S参数以及阻抗的频域曲线. 观测IC端电源网络的自阻抗 1. 用powerSi.exe打开该SPD文件

7-1 大写字母转换为小写字母(C++;cin;cout)

7-1 大写字母转换为小写字母 分数 30 作者 王群芳 单位 合肥师范学院 编程从键盘输入一个大写英文字母,将其转换为小写英文字母,将转换后的小写英文字母及其十进制的ASCII码值显示到屏幕上。如果输入的不是大写英文字母,则输出Input Data er…

MySQL数据库中存储图片和读取图片的操作

文章目录 方法一:将图片以 BLOB 类型存储在数据库中MySQL 语句实现Python 实现 方法二:将图片存储在文件系统中,并在数据库中存储路径MySQL 语句实现Python 实现 总结 在MySQL数据库中存储图片通常有两种主要方式:将图片以二进制数…

AWD入门

一、简介 AWD(Attack With Defense,攻防兼备)模式。你需要在一场比赛里要扮演攻击方和防守方,攻者得分,失守者会被扣分。也就是说攻击别人的靶机可以获取 Flag 分数时,别人会被扣分,同时你也要保护自己的主机不被别人…

强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断

强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断 目录 强心剂!EEMD-MPE-KPCA-LSTM、EEMD-MPE-LSTM、EEMD-PE-LSTM故障识别、诊断效果一览基本介绍程序设计参考资料 效果一览 基本介绍 EEMD-MPE-KPCA-LSTM(集合经验模态分解-多尺…

【JAVA】第三张_Eclipse下载、安装、汉化

简介 Eclipse是一种流行的集成开发环境(IDE),可用于开发各种编程语言,包括Java、C、Python等。它最初由IBM公司开发,后来被Eclipse Foundation接手并成为一个开源项目。 Eclipse提供了一个功能强大的开发平台&#x…

IDEA如何给debug断点加上筛选条件判断

前言 我们在使用IDEA开发Java应用时,经常是需要进行代码调试的,这就需要打断点进行操作。但有些时候,我们只希望在符合某种条件的情况下,才去到这个断点,不符合的情况下,直接跳过断点,这其实也…

ATTCK 框架讲解

摘要 ATT&CK框架作为MITRE公司开发的网络攻击行为知识库,自2015年发布以来,已成为信息安全领域的重要工具。该框架通过提炼和归纳真实世界中的网络威胁事件,以攻击者的视角构建了一套系统化的战术和技术分类体系。本文详细阐述了ATT&…

Java 中 `void` 和 `Void` 的区别

前言 在 Java 编程中,void 和 Void 是两个容易混淆的概念。虽然它们看起来相似,但实际上有着截然不同的用途和特性。 void 关键字 定义 void 是 Java 中的一个关键字。用于方法声明中,表示该方法不返回任何值。 用途 当一个方法执行某些…