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.rhkb.cn/news/457927.html

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

相关文章

Java并发学习总结:原子操作类

本文是学习尚硅谷周阳老师《JUC并发编程》的总结(文末有链接)。 基本类型原子类 AtomicIntegerAtomicLongAtomicBoolean AtomicInteger 的方法 getAndIncrement 和 incrementAndGet 的区别: 两个方法都能实现对当前值加 1 , 但…

web服务实验

http实验 先创建需要访问的web页面文件index.html 编辑vim /etc/nginx/conf.d/testip.conf 测试通过域名访问需要编辑/etc/hosts 如果通过windows的浏览器访问需要编辑下面的文件通过一管理员身份打开的记事本编辑 C:\Windows\System32\drivers\etc下的hosts文件 192.168.1…

软考:GPU算力,AI芯片

算力 FLOPS(每秒浮点操作) NVIDIA 去年就有超过 1 exa 的新闻,所以这个数值是越大越好。 AI芯片的技术架构类型 GPU:图形处理单元,擅长并行处理,适用于深度学习等AI计算密集型任务。FPGA:现…

OpenStack将运行的系统导出 QCOW2 镜像并导入阿里云

项目背景 OpenStack,作为一个开源的云计算平台,经常被用于构建私有云和公有云服务。然而,随着业务的发展和扩展,企业可能会面临将在OpenStack上运行的虚拟机迁移到其他云服务供应商的需求 需求 因为运营团队在本地机房有一台 O…

Netty-TCP服务端粘包、拆包问题(两种格式)

前言 最近公司搞了个小业务,需要使用TCP协议,我这边负责服务端。客户端是某个设备,客户端传参格式、包头包尾等都是固定的,不可改变,而且还有个蓝牙传感器,透传数据到这个设备,然后通过这个设备…

pandas快速入门

pandas快速入门 1. 创建pandas对象1.1 前言1.2 使用DataFrame类创建pandas对象1.3 对DataFrame对象进行索引1.4 使用Series类创建pandas对象1.5 对DataFrame Series对象使用常见方法 2. pandas读取文件2.1 使用pd.read_*方法读取文件2.2 使用to_*保存数据2.3 使用info()方法查看…

Python 判断键是否存在字典中(新手入门、实战案例)

在早期的Python2版本中,可以使用 dict.has_key()方法来判断一个键是否存在于字典中。 在Python3中,dict.has_key()方法被废弃了,不能再被使用。如果在Python3中尝试使用dict.has_key()方法会导致 AttributeError异常。 那在Python3中要如何判…

Linux:指令再认识

文章目录 前言一、知识点1. Linux下一切皆文件,也就是说显示器也是一种文件2. 指令是什么?3. ll 与 ls -l4. 日志5. 管道6. 时间戳 二、基本指令1. man指令2. cp指令3. mv指令4. 查看文件1)cat/tac指令——看小文件2)more/less指令…

Qt:QtCreator使用

用一个QtCreator适配所有Qt版本 首先Qt和QtCreator版本并不是通用的,一个电脑中可以安装很多个Qt版本,但只需要安装一个最新版本的QtCreator即可 Qt是一个语言,也可理解为一个SDK库,Qt目前最新版本为6.7 QtCreator是一个集成开发…

嵌入式Linux的AXI平台(platform)驱动教程

本文以JFMQL100的Linux系统的AXI接口的平台驱动为例,介绍嵌入式Linux的平台驱动编写、测试软件编写以及验证方式。本文的方法适用于任意嵌入式芯片Linux的物理地址映射的平台(platform)驱动的编写、测试与应用。 本文中AXI的开始地址为0x8000…

Python浪漫之画星星

效果图(动态的哦!): 完整代码(上教程): import turtle import random import time # 导入time模块# 创建一个画布 screen turtle.Screen() screen.bgcolor("red")# 创建一个海龟&a…

Coppelia Sim (v-REP)仿真 机器人3D相机手眼标定与实时视觉追踪 (一)

coppelia sim[V-REP]仿真实现 机器人于3D相机手眼标定与实时视觉追踪 一 标定板的制作生成标定的PDF文件PDF转为图像格式图像加载到仿真中 二 仿真场景设置加载机器人加载的控制dummy ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b48549d355d8441d8dfc20bc7ba7196…

MYSQL作业三

准备工作 查询操作

Linux复习-C++

参考博客: https://blog.csdn.net/qq_45254369/article/details/126023482?ops_request_misc%257B%2522request%255Fid%2522%253A%252277629891-A0F3-4EFC-B1AC-410093596085%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&req…

力扣 167. 两数之和 II - 输入有序数组

目录 一、题目二、思路三、代码 一、题目 二、思路 由于数组是 非递减顺序排列 的,利用该先验知识,可以设置两个指针在数组的起始和末尾,相向前进,与暴力枚举相比可以加快寻找速度。 三、代码 class Solution {public int[] tw…

面向对象(上)

1.初始对象 学习目标:理解使用对象完成数据组织的思路 可以看到加入了登记表后,我们学生所提供的信息就组织的简洁明了 程序中也是有多种多样的方式来记录数据 思考:使用变量记录数据太乱了,如果程序中也和生活中一样&#xff…

Linux - 动静态库

文章目录 一、静态库1、定义2、文件扩展名3、生成静态库4、使用静态库5、静态库的优缺点 二、动态库1、定义2、文件扩展名3、生成动态库4、使用动态库5、动态库的优缺点6、简单动态库加载 三、补充 一、静态库 1、定义 静态库是在编译时链接到最终的可执行文件中的库。这意味着…

Java Web项目实战:从零基础到项目开发全流程

Java Web开发环境搭建 Java Web开发需要Java运行环境、IDE(如IntelliJ IDEA或Eclipse)以及Maven集成开发工具等。首先,确保电脑上安装有Java 8或更高版本,可以通过访问Java官网获取最新版本。其次,安装IDE&#xff0c…

深入理解跳出率:如何利用百度统计优化网站用户体验

在数字营销的世界中,跳出率是一个关键指标,它衡量了用户对网站的第一印象和内容的吸引力。最近,我在分析我的网站数据时发现,跳出率常常高达100%,这促使我深入研究了跳出率的含义和影响因素。 跳出率的定义与计算 跳…

AndroidStudio Koala更改jdk版本 2024-1-2

升级android studio版本到 AndroidStudio Koala之后,发现修改jdk版本的方式不同了。如下: 修改jdk版本