当前位置: 首页 > news >正文

@Transational事务注解底层原理以及什么场景事务会失效

@Transactional的底层是如何实现的

底层是通过动态代理实现的。Spring Boot 在运行时会生成一个代理对象,该代理对象被注解的方法调用,并在方法调用前后进行事务管理,事务管理包括开启事务,提交事务或回滚事务等操作。
1开启事务
2执行业务逻辑
3提交/回滚事务


@Transational中常见的参数有哪些

value-指定bean的名称

指定事务管理器的 bean 名称。当应用中存在多个事务管理器时,可以通过该参数指定要使用的事务管理器

@Transactional(value = "myTransactionManager")
public void someMethod() {// 业务逻辑
}

propagation-指定Spring事务的传播行为

指定事务的传播行为,即当一个事务方法被另一个事务方法调用时,事务如何进行传播。Spring 定义了 7 种传播行为,常用的有以下几种:

  • Propagation.REQUIRED(默认值):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • Propagation.REQUIRES_NEW:无论当前是否存在事务,都会创建一个新的事务,并且挂起当前事务(如果存在)。
  • Propagation.NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。
  • Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
  • Propagation.MANDATORY:表示该方法必须在一个事务中运行,如果当前没有事务,则抛出异常。
  • Propagation.NEVER:表示该方法不能在一个事务中运行,如果当前存在事务,则抛出异常。
  • Propagation.NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void someMethod() {// 业务逻辑
}

timeout-事务的超时时间

@Transactional(timeout = 5)
public void someMethod() {// 业务逻辑
}

readOnly-事务只读不可进行写操作

@Transactional(readOnly = true)
public void someMethod() {// 只读业务逻辑
}

rollbackFor-遇到哪些异常回滚

指定哪些异常类型会导致事务回滚。可以指定多个异常类型,用逗号分隔

@Transactional(rollbackFor = {SQLException.class, MyCustomException.class})
public void someMethod() throws SQLException, MyCustomException {// 业务逻辑
}

什么情况会导致@Transactional失效 

1.添加到非public方法上

2.使用try catch处理异常

3.调用类内部的Transactional注解(嵌套使用)

4.事务的传播机制使用不当

5.数据库不支持事务


为什么@Transational注解内部调用会导致事务失效呢? 

Spring 的 @Transactional 注解是基于 AOP(面向切面编程)实现的。AOP 通过代理模式为目标对象创建代理对象,在代理对象中织入事务管理的逻辑,例如在方法调用前后开启、提交或回滚事务

当外部调用带有 @Transactional 注解的方法时,实际上是调用的代理对象的方法,代理对象会处理事务相关的操作

当在同一个类的一个方法中调用另一个带有 @Transactional 注解的方法时,这种调用属于内部调用

内部调用时,并没有经过代理对象,而是直接调用了目标对象的方法,绕过了 AOP 代理的事务增强逻辑,从而导致事务失效


为什么参数rollbackFor要用Exception.class

如果不配置Exception.class的话,事务只会遇到RunTimeException的时候回滚

如果配置了的话,那么事务遇到非运行时异常时也回滚

也就是我们的Exception包含了所有异常,这个的意思是我们遇到异常就回滚,而不是遇到特定的运行时异常RunTimeException的时候回滚


如果想要嵌套事务调用@Transational修饰的方法生效该怎么办

方法一:注入自身 Bean

在类中通过依赖注入自身的 Bean,然后使用注入的 Bean 进行内部方法调用,这样就可以通过代理对象调用方法,使事务注解生效

因为我们Bean注入了,所以这个对象可以通过代理对象调用方法

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {// 注入自身的 Bean@Autowiredprivate UserService self;public void outerMethod() {// 通过注入的 Bean 调用带有 @Transactional 注解的方法self.innerMethod();}@Transactionalpublic void innerMethod() {// 业务逻辑System.out.println("执行内部方法的业务逻辑,事务生效");}
}

方法二:使用 AopContext.currentProxy() 获取代理对象

在配置类中开启 exposeProxy = true,之后在代码里使用 AopContext.currentProxy() 获取当前代理对象,再通过代理对象调用方法

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.framework.AopContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;// 配置类,开启 exposeProxy
@Configuration
@EnableAspectJAutoProxy(exposeProxy = true)
class AopConfig {// 可以添加其他配置
}@Service
public class UserService {public void outerMethod() {// 获取代理对象并调用带有 @Transactional 注解的方法((UserService) AopContext.currentProxy()).innerMethod();}@Transactionalpublic void innerMethod() {// 业务逻辑System.out.println("执行内部方法的业务逻辑,事务生效");}
}

方法三:getBean方法获取自身Bean实例

这种方法是和注入Bean是一样的

借助 ApplicationContext 获取 Bean 实例。首先要将 ApplicationContext 注入到服务类中,然后使用 getBean 方法获取自身 Bean 实例,再通过该实例调用带有 @Transactional 注解的方法

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class UserService implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}public void outerMethod() {// 通过 getBean 方法获取自身 Bean 实例UserService self = applicationContext.getBean(UserService.class);// 调用带有 @Transactional 注解的方法self.innerMethod();}@Transactionalpublic void innerMethod() {// 业务逻辑System.out.println("执行内部方法的业务逻辑,事务生效");}
}

相关文章:

@Transational事务注解底层原理以及什么场景事务会失效

Transactional的底层是如何实现的 底层是通过动态代理实现的。Spring Boot 在运行时会生成一个代理对象,该代理对象被注解的方法调用,并在方法调用前后进行事务管理,事务管理包括开启事务,提交事务或回滚事务等操作。 1开启事务 …...

Linux扩容磁盘

启动 fdisk sudo fdisk /dev/sda输入p命令查询分区列表 输入d命令删除所有分区 需要一个一个删 输入n命令创建新分区 40G可以不用输入,直接回车使用默认 输入w命令保存操作 查看分区情况 sudo fdisk -l会发现sda1不是启动分区(Boot列不是号&a…...

全面解析鸿蒙(HarmonyOS)开发:从入门到实战,构建万物互联新时代

文章目录 引言 一、鸿蒙操作系统概述二、鸿蒙开发环境搭建三、鸿蒙核心开发技术1. **ArkUI框架**2. **分布式能力开发**3. **原子化服务与元服务** 四、实战案例:构建分布式音乐播放器五、鸿蒙开发工具与调试技巧六、鸿蒙生态与未来展望结语 引言 随着万物互联时代…...

Uniapp 原生组件层级过高问题及解决方案

文章目录 一、引言🏅二、问题描述📌三、问题原因❓四、解决方案💯4.1 使用 cover-view 和 cover-image4.2 使用 subNVue 子窗体4.3 动态隐藏原生组件4.4 使用 v-if 或 v-show 控制组件显示4.5 使用 position: fixed 布局 五、总结&#x1f38…...

Android adb测试常用命令大全

目录 一、查看最上层成activity名字: 二、查看Activity的任务栈: 三、获取安装包信息 四、性能相关 1、显示CPU信息 : 2、查看CPU使用信息 3、内存信息(meminfo package_name or pid 使用程序的包名或者进程id显示内存信息) 4、电量信…...

linux的基础入门2

linux的root用户 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 在Linux系统中,拥有最大权限的账户名为:root(超级管理员) 而在前期,我们一直使用的账户是普通的用户 普通用户的权限,一般在其HOME目录内是不受限的 一旦出了HOME目录…...

19.4.8 数据库综合运用

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 需要北风数据库的请留言自己的信箱。 本节中将通过实例综合展示对数据表的查询、增加、修改和删除。 【例 19.16】【项目&#xf…...

JAVA中的抽象学习

一、Java SE 中的抽象概念 在 Java 中,抽象(Abstraction)是面向对象编程的重要特性之一。抽象的核心思想是“只关注重要的特性,而忽略不重要的细节”。抽象通常通过抽象类和接口来实现,它帮助开发者将复杂的系统隐藏在…...

在 Go 中实现事件溯源:构建高效且可扩展的系统

事件溯源(Event Sourcing)是一种强大的架构模式,它通过记录系统状态的变化(事件)来重建系统的历史状态。这种模式特别适合需要高可扩展性、可追溯性和解耦的系统。在 Go 语言中,事件溯源可以通过一些简单的…...

加解密 | AES加、解密学习

加解密 | AES加、解密学习 你的代码实现了一个简单的AES(高级加密标准)加密和解密的测试程序。以下是对代码的分析和一些改进建议: 代码功能 初始化数据和密钥: 定义了一个16字节的输入数据 input_data。定义了一个16字节的AES…...

【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】CSS样式解析:行内、内部与外部样式的区别与优先级分析

简介 2025年计算机视觉研究进展与应用(ACVRA 2025)将于2025年2月28-3月2日在中国广州召开,会议将汇聚世界各地的顶尖学者、研究人员和行业专家,聚焦计算机视觉领域的最新研究动态与应用成就。本次会议将探讨前沿技术,…...

MongoDB 基本操作

一、数据库操作 1. 切换或创建数据库 使用use命令切换到指定数据库,若该数据库不存在,在首次插入数据时会自动创建。 use myDatabase 2. 查看所有数据库 使用show dbs命令查看 MongoDB 实例中的所有数据库。 show dbs 3. 删除当前数据库 使用db.…...

Eclipse JSP/Servlet 深入解析

Eclipse JSP/Servlet 深入解析 引言 随着互联网的快速发展,Java Web开发技术逐渐成为企业级应用开发的主流。在Java Web开发中,JSP(JavaServer Pages)和Servlet是两个核心组件,它们共同构成了Java Web应用程序的基础。本文将深入解析Eclipse平台下的JSP/Servlet技术,帮…...

Hyperledger caliper 性能测试

前言:Hyperledger caliper 的本质是使用node对被测试网络进行压力测试,因此需要nodejs。本次使用 Hyperledger caliper 0.5 对 fabric 1.4.6进行压测 准备条件:nodejs 16 (略 linux下 解压环境变量即可) # 创建工作…...

Record-Mode 备案免关站插件,让 WordPress 备案不影响 SEO 和收录

专为 WordPress 网站设计的实用工具,旨在帮助网站在备案期间无需关闭即可正常收录所有页面的信息,利于SEO。 功能特性 免关站展示:开启插件后,非管理员用户访问网站时,会看到以半透明遮罩层或不透明全屏遮罩样式呈现的…...

【Java 面试 八股文】Redis篇

Redis 1. 什么是缓存穿透?怎么解决?2. 你能介绍一下布隆过滤器吗?3. 什么是缓存击穿?怎么解决?4. 什么是缓存雪崩?怎么解决?5. redis做为缓存,mysql的数据如何与redis进行同步呢&…...

介绍几款免费的显示器辅助工具!

今天为大家介绍几款实用的显示器辅助软件,它们可以帮助你轻松切换显示源调节、显示器亮度,甚至优化显示效果,让你的屏幕使用体验更加便捷和舒适。 Monitor Brightness Adjuster-多屏幕亮度调节工具 如果你需要同时使用多个显示器&#xff0…...

django配置跨域

1、第一种 from django.views.decorators.csrf import csrf_exemptcsrf_exempt第二种 安装 pip install django-cors-headers在配置文件settings.py进入 INSTALLED_APPS [..."corsheaders", # 添加 ]MIDDLEWARE [corsheaders.middleware.CorsMiddleware, # 添加…...

web前端第三次作业

题目 本期作业 WEB第三次作业 请使用JS实一个网页中登录窗口的显示/隐藏&#xff0c;页面中拖动移动&#xff0c;并且添加了边界判断的网页效 代码图片 效果展示 代码 <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8&qu…...

【Pandas】pandas Series align

Pandas2.2 Series Computations descriptive stats 方法描述Series.align(other[, join, axis, level, …])用于将两个 Series 对齐&#xff0c;使其具有相同的索引 pandas.Series.align pandas.Series.align() 方法用于将两个 Series 对齐&#xff0c;使其具有相同的索引。…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...