当前位置: 首页 > 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;使其具有相同的索引。…...

常用函数库之 - std::function

std::function 是 C11 引入的通用可调用对象包装器&#xff0c;用于存储、复制和调用任意符合特定函数签名的可调用对象&#xff08;如函数、lambda、函数对象等&#xff09;。以下是其核心要点及使用指南&#xff1a; ​​核心特性​​ ​​类型擦除​​ 可包装任意可调用对…...

Codeforces Round 1025 (Div. 2) B. Slice to Survive

Codeforces Round 1025 (Div. 2) B. Slice to Survive 题目 Duelists Mouf and Fouad enter the arena, which is an n m n \times m nm grid! Fouad’s monster starts at cell ( a , b ) (a, b) (a,b), where rows are numbered 1 1 1 to n n n and columns 1 1 1 t…...

TDengine 开发指南——无模式写入

简介 在物联网应用中&#xff0c;为了实现自动化管理、业务分析和设备监控等多种功能&#xff0c;通常需要采集大量的数据项。然而&#xff0c;由于应用逻辑的版本升级和设备自身的硬件调整等原因&#xff0c;数据采集项可能会频繁发生变化。为了应对这种挑战&#xff0c;TDen…...

第34次CCF-CSP认证真题解析(目标300分做法)

第34次CCF-CSP认证 矩阵重塑&#xff08;其一&#xff09;AC代码及解析矩阵重塑&#xff08;其二&#xff09;AC代码及解析货物调度AC代码及解析 矩阵重塑&#xff08;其一&#xff09; 输入输出及样例&#xff1a; AC代码及解析 1.线性化原矩阵 &#xff1a;由于cin的特性我们…...

N元语言模型 —— 一文讲懂!!!

目录 引言 一. 基本知识 二.参数估计 三.数据平滑 一.加1法 二.减值法/折扣法 ​编辑 1.Good-Turing 估计 ​编辑 2.Back-off (后备/后退)方法 3.绝对减值法 ​编辑4.线性减值法 5.比较 三.删除插值法(Deleted interpolation) 四.模型自适应 引言 本章节讲的…...

第5章:Cypher查询语言进阶

在掌握了Cypher的基础知识后&#xff0c;本章将深入探讨更高级的查询技术。这些进阶技能将帮助您构建更复杂、更高效的查询&#xff0c;解决实际业务中的复杂问题&#xff0c;并充分发挥Neo4j的图数据处理能力。 5.1 复杂查询构建 随着业务需求的复杂性增加&#xff0c;查询也…...

c#bitconverter操作,不同变量类型转byte数组

缘起:串口数据传输的基础是byte数组&#xff0c;write(buff,0,num)或者writeline(string)&#xff0c;如果是字符串传输就是string变量就可以了&#xff0c;但是在modbus这类hex传递时&#xff0c;就要遇到转换了&#xff0c;拼凑byte数组时需要各种变量的值传递&#xff0c;解…...

青少年编程与数学 01-011 系统软件简介 07 iOS操作系统

青少年编程与数学 01-011 系统软件简介 07 iOS操作系统 一、发展历程&#xff08;一&#xff09;诞生初期&#xff08;2007 - 2008年&#xff09;&#xff08;二&#xff09;功能拓展与升级&#xff08;2009 - 2013年&#xff09;&#xff08;三&#xff09;持续优化与创新&…...

SDC命令详解:使用set_propagated_clock命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 指定端口列表/集合 简单使用 注意事项 传播时钟是在进行了时钟树综合后&#xff0c;使用set_propagated_clock命令可以将一个理想时钟转换为传播时钟&#x…...

现代C++特性(一):基本数据类型扩展

文章目录 基础数据类型long long (C 11)numeric_limits()获取当前数据类型的最值warning C4309: “”: 截断常量值新字符类型char16_t和char32_tWindows编程常用字符类型wchar_tchar8_t (C 20) 基础数据类型 C中的基本类型是构建其他数据类型的基础&#xff0c;常见的基础类型…...