SpringBoot事务管理:自调用与事务回滚行为分析

一、背景

在Spring Boot应用中,事务管理是确保数据一致性和完整性的关键机制。通过使用@Transactional注解,可以轻松地管理数据库操作的事务。然而,开发者在方法调用时可能会遇到事务不生效或回滚不按预期执行的情况

二、问题描述

在某服务类BillService中,有两个方法:a和b。a方法调用b方法,b方法使用了@Transactional注解。由于a方法未声明事务,直接在同一类中调用b时,Spring不会应用b的事务管理。

@Service
public class BillService {public void a() {b();}@Transactional(rollbackFor = Exception.class)public void b() {// 业务逻辑}
}


调用情况:
a()方法调用b()方法(直接调用)。
b()方法抛出异常时,a()方法未被标记为事务。
结果:b中的事务将无效,异常不会导致事务回滚,可能导致数据不一致。

三、分析


Spring AOP 代理机制:
Spring的事务管理依赖于代理模式。当方法在同一类内部直接调用时,Spring无法识别为代理调用,因此不会激活事务管理。
异常处理:
由于a方法没有声明为事务,b中的异常将不会导致任何回滚


四、解决方案


为了确保b方法的事务能够生效并正确回滚,可以考虑以下几种解决方案:

4.1.自调用改为代理调用:

    将b方法的调用改为通过注入自身的方式进行调用,确保事务管理生效。
    

@Service
public class BillService {@Autowiredprivate BillService billService; // 注入自身public void a() {billService.b(); // 通过代理调用b}@Transactional(rollbackFor = Exception.class)public void b() {// 业务逻辑}
}

  
  4.2.将方法分离到不同的服务中:

    创建一个新的服务类,例如BillTransactionService,将b方法移到该类中,以便通过代理机制调用。
  

@Service
public class BillService {@Autowiredprivate BillTransactionService billTransactionService;public void a() {billTransactionService.b(); // 通过不同服务调用b}
}@Service
public class BillTransactionService {@Transactional(rollbackFor = Exception.class)public void b() {// 业务逻辑}
}
4.3.在a方法中声明事务:

    如果a方法的逻辑需要与b方法的事务保持一致,可以在a方法上添加@Transactional注解,但要注意异常的处理逻辑。

@Service
public class BillService {@Transactional(rollbackFor = Exception.class)public void a() {b(); // 此时可以直接调用b}@Transactional(rollbackFor = Exception.class)public void b() {// 业务逻辑}
}

五、spring 自我注入(即在一个类中注入自身)是否会导致循环依赖或异常

在Spring中,自我注入(即在一个类中注入自身)是允许的,导致循环依赖或异常。Spring会正确处理自我注入,
因为它会创建一个代理对象来实现事务管理。

5.1、工作原理

5.1.1 1.代理模式:当你使用@Autowired注解注入自身时,Spring会创建一个代理实例。这个代理实例在内部持有实际的BillService实例。通过代理对象调用b()方法时,Spring的事务管理会生效。

5.1.2 没有死循环:在注入自身的情况下,Spring会处理依赖关系,不会导致无限递归调用,因此不会产生死循环。

5.2 注意事项

5.2.1 事务传播:确保在b()方法内有适当的异常处理。如果b()抛出异常并且你希望事务回滚,请确保b()方法使用了@Transactional注解。

5.2.2 Spring上下文:确保你的Spring上下文配置正确,以便能够正常管理你的服务和事务。

5.3 示例代码

下面是自我注入的一个简单示例:
 

@Service
public class BillService {@Autowiredprivate BillService billService; // 注入自身public void a() {billService.b(); // 通过代理调用b}@Transactional(rollbackFor = Exception.class)public void b() {// 业务逻辑// 可能会抛出异常,导致事务回滚}
}

5.4 总结

自我注入在Spring中是安全的,并且是实现事务管理的有效方式。只要确保异常处理和事务传播策略得当,就可以正常使用。


六、结论

在Spring Boot中,确保事务管理的有效性需要注意方法调用的方式。通过使用代理调用或将相关逻辑分离到不同的服务中,
可以有效地管理事务,并确保异常处理和回滚机制按预期工作。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

STM32 + CubeMX + 硬件SPI + W5500 +TcpClient

这篇文章记录一下STM32W5500TCP_Client的调试过程,实现TCP客户端数据的接收与发送。 目录 一、W5500模块介绍二、Stm32CubeMx配置三、Keil代码编写1、添加W5500驱动代码到工程(添加方法不赘述,驱动代码可以在官网找)2、在工程中增…

template advanced

一.仿函数再探 stl_stack/queue-CSDN博客 在priority_queue中,我们介绍了仿函数作为第三个参数来改变堆的类型,而仿函数还有其他的用处。 那么我们是否可以借助优先级队列来对日期类进行排序呢? 答案是可以的,但前提是该日期…

spring源码[spring启动流程]

spring启动流程 AnnotationConfigApplicationContext的构造方法 1.父类构造方法,构造一个DefaultListableBeanFactory 在调用AnnotationConfigApplicationContext的构造方法之前,会调用父类GenericApplicationContext的无参构造方法,会构造…

使用Python做一个微信机器人

使用Python制作微信机器人是一个有趣且实用的项目,它可以让您自动化处理微信消息、监控微信群、甚至实现智能聊天等功能。 请求参数 Header 参数 export interface ApifoxModel {"X-GEWE-TOKEN": string;[property: string]: any; } Body 参数applicat…

Python-创建并调用自定义文件中的模块/函数

背景:在Python编程中,我们常常需要创建自己的专属文件,以便帮助我们更高效,快捷地完成任务。那么在Python中我们怎么创建并调用自己文件中的模块/函数呢? 在Python中调用自定义文件,通常是指调用自己编写的Python模块…

【C++】C++17结构化绑定、std::optional、std::variant、std::any

二十二、C17中的结构化绑定、std::optional、std::variant、std::any 本部分是一个小系列,介绍C17中新引入的、用来解决各种不同返回情况的、标准库新组件。 1、C的结构化绑定 结构化绑定structured bindings是C17中引入的一项特性,它允许开发者方便地…

ntkrnlmp.exe导致蓝屏死机的解决方法

在使用Windows操作系统的过程中,用户可能会遇到由ntkrnlmp.exe文件错误引发的蓝屏死机(Blue Screen of Death, BSOD)问题,这不仅影响了日常的工作效率,也可能造成数据丢失的风险。本文将为您提供一系列即时排查与修复n…

U3D游戏开发之骨骼动画相关

目录 1 作为U3D程序如何制作骨骼动画 2 骨骼动画程序代码相关 这个内容我在很久之前就想写了,很多项目也与骨骼动画挂钩,今天我们揭秘的是2D骨骼动画。来聊一聊大家可能非常关注的两个问题:作为程序如何制作骨骼动画?接到美术的骨…

java:题目:用Java实现简单的自取取款操作

import java.util.Scanner; public class ATM {public static void main(String[] args){//自主取款主类Scanner scnew Scanner(System.in);System.out.println("请输入账户号码:");String BankAccoutsrsc.nextLine();/BankAccout3 newBankAccoutnew Bank…

VLAN 高级技术 ——QinQ的配置

QinQ的概述: QinQ技术是一种扩展虚拟局域网(VLAN)数量空间的技术,通过在802.1Q标签报文的基础上再增加一层802.1Q的Tag来实现。以下是对QinQ技术的详细概述: QinQ技术的定义与背景 定义:QinQ&#xff08…

不得不承认供电公司信息宣传向媒体投稿的好方法找到了

初入国网供电公司,我被分配到了信息宣传部门,负责每月的信息宣传投稿任务。这项任务看似简单,实则充满挑战。一开始,我满怀热情,以为只要写出高质量的文章,就能顺利发表。然而,现实给了我当头一棒。传统的邮箱投稿方式,不仅竞争压力大,审核严格,而且周期漫长。每次投稿后,我总是…

『YOLOV5』| 一文搞定训练过程中的意外终止、以及想继续增加训练轮数!

文章目录 情况一:意外训练中断(程序未训练完成,想完成目标训练轮数)情况二:自动训练完成(程序已完成训练,想增加训练轮数) 情况一:意外训练中断(程序未训练完…

GCC编译器的`-Wall`、`-Wextra`和`-pedantic`选项解读

gcc是广泛使用的开源编译器,-Wall、-Wextra和-pedantic是gcc中用于控制警告信息的选项,以下是详细介绍: -Wall(启用大部分警告) 功能:-Wall 选项用于启用一系列常用的警告信息,这些警告能帮助…

MMBench-Video:上海 AI Lab 联合多所高校推出长视频理解基准测试工具,全面评估 LVLMs 视频理解的能力

❤️ 如果你也关注大模型与 AI 的发展现状,且对大模型应用开发非常感兴趣,我会快速跟你分享最新的感兴趣的 AI 应用和热点信息,也会不定期分享自己的想法和开源实例,欢迎关注我哦! 🥦 微信公众号&#xff…

高频电子线路---调角频谱与频宽

目录 调角频谱(FM单频调制) 带宽 调频方法 直接调频方法与电路 变容二极管 如何提升频偏? 1. 增大调制信号的幅度(增大调制深度) 2. 提高调制信号的频率 3. 提高调制深度(调制指数) 4. 增加发射功率 5. 使用特殊的调制…

摘要、数字签名、对称加密、非对称加密综合应用示例以及技术原理说明

图:介绍了数字信封的安全传输过程 关键术语 散列:Hash(哈希),一般翻译做散列、杂凑,是把任意长度的输入(数据信息)通过散列算法变换成固定长度的输出,该输出就是散列值…

java学习3---面向对象

一、设计对象并使用 1.类和对象 类是共同特征的描述;对象是真实存在的具体实例。 2.类的几个补充注意事项 二、封装 对象代表什么,就得封装对应的数据,并提供数据对应的行为。 封装告诉我们如何正确的设计对象 三、this关键字 this可以区…

Maven

Maven 命令方式构建项目 mvn compile:编译项目,生成target文件(不编译测试代码) mvn package:打包项目,生成jar或war文件(不指定默认jar包) mvn clean:清理编译或打包后…

leetcode 173.二叉搜索树迭代器

1.题目要求: 2.题目代码: /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nu…

vue插件清除 所有console.log()

一、作用 1、提升性能console.log() 语句会消耗一定的性能,尤其是在频繁调用的情况下。在生产环境中移除这些语句可以提高应用的运行效率。 2、减少信息泄露console.log() 可以输出敏感信息(如用户数据、API 响应等)。在生产环境中&#xf…