Spring之事务原理篇

news2024/11/17 3:55:36

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨
👀👀👀 个人博客:小奥的博客
👍👍👍:个人CSDN
⭐️⭐️⭐️:Github传送门
🍹 本人24应届生一枚,技术和水平有限,如果文章中有不正确的内容,欢迎多多指正!
📜 欢迎点赞收藏关注哟! ❤️

文章目录

  • Spring之事务原理篇
    • 1. Spring事务的实现方式
    • 2. Spring事务的事务传播行为有几种
    • 3. @Transactional的本质是什么
    • 4. Spring事务失效的场景
    • 5. @Transactional方法自调用如何解决
    • 6. Spring事务的隔离级别

Spring之事务原理篇

1. Spring事务的实现方式

  • 编程式事务 : 在代码中硬编码(不推荐使用) : 通过 TransactionTemplate或者 TransactionManager 手动管理事务,实际应用中很少使用,但是对于你理解 Spring 事务管理原理有帮助。
  • 声明式事务 : 在 XML 配置文件中配置或者直接基于注解(推荐使用) : 实际是通过 AOP 实现(基于@Transactional 的全注解方式使用最多)

另外,在官方文档中也有关于Spring事务的实现原理的简单概述:

关于Spring框架的声明性事务支持,最重要的概念是这种支持是通过 AOP代理 实现的,而且事务advice是由元数据(目前是基于XML或注解)驱动的。AOP与事务元数据的结合产生了一个AOP代理,它使用 TransactionInterceptor 与适当的 TransactionManager 实现来驱动围绕方法调用的事务。

@Transactional 通常与 PlatformTransactionManager 管理的线程绑定的事务一起工作,将一个事务暴露给当前执行线程内的所有数据访问操作。注意:这不会传播到方法内新启动的线程。

ReactiveTransactionManager 管理的响应式事务使用 Reactor 上下文而不是 thread-local 属性。因此,所有参与的数据访问操作都需要在同一 reactive pipeline 中的同一 Reactor 上下文中执行。

下图显示了在事务型代理上调用方法的概念性视图:

在这里插入图片描述

2. Spring事务的事务传播行为有几种

Spring事务传播行为是为了解决业务层方法之间互相调用的事务问题

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。

Spring中定义了7种传播行为,如表所示:

传播行为含义
PROPAGATION_REQUIRED(required默认级别)如果存在一个事务,则支持当前事务。
如果没有事务,则开启新事务
PROPAGATION_REQUIRES_NEW(requires_new)总是开启一个新的事务。
如果一个事务已经存在,则新建一个事务,新老事务相对独立。
外部事务抛出异常回滚不影响内部事务的正常提交。
PROPAGATION_NESTED(nested)如果一个活动的事务存在,则运行一个嵌套的事务中;
如果没有活动事务,则新建一个事务。
PROPAGATION_SUPPORTS(supports)如果存在一个事务,则支持当前事务。
如果没有事务,则以非事务的方法执行
PROPAGATION_NOT_SUPPORTED(not_support)总是非事务地执行,并挂起任何存在的事务
PROPAGATION_MANDATORY(mandatory)强制事务执行,如果不存在当前事务,抛出异常
PROPAGATION_NEVER(never)非事务方式执行,如果存在当前事务,抛出异常

3. @Transactional的本质是什么

@Transactional注解仅仅是一些和事务相关的元数据,在运行时被事务基础设施读取消费,并使用这些元数据来配置Bean的事务行为。一是表明该方法要参与事务,二是配置相关属性来定制事务的参与方式和行为。

声明式事务底层是通过AOP实现的,@Transactional注解使用环绕通知,在进入方法前开启事务,使用try-catch包含目标方法,执行目标方法,如果执行完成后没有出现异常,就提交事务,否则就回滚事务。

@Transactional注解既可以标注在类上,也可以标注在方法上。当在类上时,默认应用到类里的所 有方法。如果此时方法上也标注了,则方法上的优先级高。 另外注意方法一定要是public的。

4. Spring事务失效的场景

Spring框架提供了非常方便的事务管理机制,但是在某些情况下,Spring事务会失效。

(1)方法非public。如果一个方法不是public修饰的,那么Spring无法代理这个方法,Spring官方文档中有明确的说明,@Transactional只有在修饰public方法时才会生效。修改pretected、private或者保内可见的方法均不会生效。

(2)事务方法被final、static关键字修饰。事务方法被final修改会防止子类重写该方法,从而无法进行动态代理,事务方法被static修改会使得该方法属于类而不是对象,因此也无法进行动态代理。

(3)方法自调用。当一个类中的一个方法调用同一个类中的另一个@Transactional方法时,这种情况被称为方法自调用,在这种情况下,事务控制将无法正常工作。因为事务代理对象在外部调用时才会被创建,如果一个方法在同一个类中调用另一个方法,实际上是在当前实例中进行调用,而不是通过代理对象调用。

(4)异常被捕获。Spring默认只对未被捕获的异常进行回滚,如果异常被捕获并处理了,那么Spring无法感知到异常的存在,也就无法进行回滚,因此,如果需要事务回滚,必须确保异常未被捕获并没有被处理。

(5)没有被Spring管理。只有在Spring容器中管理的Bean上的@Transactional注解才会生效,如把@Service注解注释掉,这个类就不会被加载成为一个Bean,在该对象的方法上添加@Transactional注解将不会有任何效果。

(6)数据库不支持事务。Spring事务是通过底层的数据库事务实现的。如果底层数据库不支持事务,那么Spring自然无法实现事务管理,如果需要使用事务,选择支持事务的数据库引擎,如MySQL的InnoDB引擎。

5. @Transactional方法自调用如何解决

@Transactional方法自调用时事务会失效:

	@Override
    public Integer add() {
        return add2();
    }
    @Transactional(rollbackFor = Exception.class)
    public Integer add2() {
        int res = userMapper.add();
        res = 1 / 0;
        return 1;
    }

如上代码,即时抛出了异常,事务也不会生效。

(1)更改为外部调用。将更新数据表的操作重新抽取成一个service,并将其注入Spring容器管理。

对于上述代码,我们可以将add2()方法重新抽取成一个TestServiceImpl,然后交给Spring管理,重新注入,如果发生异常事务就会回滚。

(2)使用编程式事务。对更新表的操作的逻辑代码使用编程式事务处理,这样即使加了@Transactional注解的方法是private的也可以被事务管理。

	@Override
    public Integer add() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                add2();
            }
        });
        return 1;
    }

    @Autowired
    private TransactionTemplate transactionTemplate;

    // @Transactional(rollbackFor = Exception.class)
	// 这时,即使方法改为private一样事务会生效
    public Integer add2() {
        int res = userMapper.add();
        res = 1 / 0;
        return 1;
    }

6. Spring事务的隔离级别

Spring本身支持的事务其实本质上还是通过数据库的事务来实现的,所以Spring事务的隔离级别和数据库的隔离级别是一样的。

(1)default。Spring默认的隔离级别,表示使用数据库默认的事务隔离级别。

(2)read_uncommitted(读未提交)。事务最低的隔离级别,允许一个事务可以看到其他事务未提交的数据。这种隔离级别会产生脏读、不可重复读和幻读。

(3)read_committed(读已提交)。这是Sql Server、Oracle默认隔离级别,保证一个事务修改的数据提交后才能被其他事务读取,这种隔离级别可以避免脏读,但是可能会出现不可重复读和幻读。

(4)repeatable_read(可重复读)。这是MySQL-innodb默认隔离级别,可以放置脏读、不可重复读,但是可能出现幻读。

(5)serializable(可串行化)。事务被处理为顺序执行。防止脏读、不可重复读、幻读。

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

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

相关文章

opencv各个模块介绍(1)

Core 模块:核心模块,提供了基本的数据结构和功能。 常用的核心函数: cv::Mat:表示多维数组的数据结构,是OpenCV中最常用的类之一,用于存储图像数据和进行矩阵运算。 cv::Scalar:用于表示多通道…

Redis - 高并发场景下的Redis最佳实践_翻过6座大山

文章目录 概述6座大山之_缓存雪崩 (缓存全部失效)缓存雪崩的两种常见场景如何应对缓存雪崩? 6座大山之_缓存穿透(查询不存在的 key)缓存穿透的原因解决方案1. 数据校验2. 缓存空值3. 频控4. 使用布隆过滤器 6座大山之_…

水果检测15种YOLOV8

水果检测15种YOLOV8,只需要OPENCV,采用YOLOV8训练得到PT模型,然后转换成ONNX,OPENCV调用,支持C/PYTHON/ANDROID开发

41 arr.at is not a function

前言 一台机器 获取前端服务1, 一个列表能够展示出来 然后 一台机器 同样获取前端服务1, 这个列表展示不出来 然后 console里面没有任何报错[实际上是有报错, 但是没看到, 需要在vue的js代码里面去调试] 然后 这里面最终出现问题的地方是 Array.at 的使用, 我这边 js引擎版…

Spring Security安全管理

目录 一.添加依赖 效果 二.设置配置文件 认证 1.密码生成器 BCryptPasswordEncoder 配置文件中 2.inMemoryAuthentication内存认证方法 授权 效果 登录 效果 三.UserDetailsService认证授权方式 新建数据库 实体类 Role User 接口 实现类 配置文件 效果 四…

(AtCoder Beginner Contest 325) ---- D - Printing Machine -- 题解

目录 D - Printing Machine: 题目大意: 思路解析: 代码实现: D - Printing Machine: 题目大意: 思路解析: 打印一次后,需要充电一微秒后才能再次打印就可以看作每微妙只能打印一…

Vue3更新Package.json版本号

由于我之前已经更新过了,下面的方法提示我已经是最新的了,记录一下,过段时间在测试一下 npm install -g vue/clivue upgrade

Gitee删除自己本地仓库

1、打开自己的本地仓库 2、点击管理 3、选择删除仓库 4、将□的内容复制到⭕里

文件上传一-WEB攻防-PHP应用文件上传函数缺陷条件竞争二次渲染黑白名单JS绕过9

演示案例: PHP-原生态-文件上传-前后端验证PHP-原生态-文件上传-类型文件头验证PHP-原生态-文件上传-后缀黑白名单验证PHP-原生态-文件上传-解析配置&二次渲染PHP-原生态-文件上传-逻辑缺陷&函数缺陷 #学习前必读: 1、课前一定要明白&#xff1a…

nginx: [emerg] stream directive is duplicate in /etc/nginx/nginx.conf:56

背景: 在维护paas平台的时候发现一个web前端容器服务运行报错,提示如下: 问题分析: 根据日志的内容,发现是nginx.conf配置文件的stream模块配置存在问题导致的。需要查看一下nginx.conf配置文件的内容: 注…

LeetCode Python - 73. 矩阵置零

目录 题目描述解法方法一:数组标记方法二:原地标记 运行结果方法一方法二 题目描述 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:…

FFmpeg拉取RTSP流并定时生成10秒短视频

生成效果: 视频时长为10秒 生成格式为FLV 输出日志: 完整实现代码如下: 需要在Mac和终端先安装FFmpeg brew install ffmpeg CMake文件配置: cmake_minimum_required(VERSION 3.27) project(ffmpeg_open_stream) set(CMAKE_CXX_STANDARD 17)#头文件包目录 include_director…

可调恒流电子负载优点和应用

可调恒流电子负载是一种可以模拟真实负载的电子设备,它可以在电源电压和电流范围内提供恒定的电流或电压。这种设备在许多领域都有广泛的应用,如电力系统、通信设备、汽车电子、航空航天等。以下是可调恒流电子负载的优点和应用。 优点: 精确…

HarmonyOS NEXT应用开发之ArkWeb同层渲染

介绍 该方案展示了ArkWeb同层渲染:将系统原生组件直接渲染到前端H5页面上,原生组件不仅可以提供H5组件无法实现的一些功能,还能提升用户体验的流畅度 效果图预览 使用说明 进入页面即可看到同层渲染效果,Text,searc…

-bash: ./1.sh: /bin/bash^M: bad interpreter: No such file or directory解决方法

1、执行脚本 ./1.sh时报如下错误 -bash: ./1.sh: /bin/bash^M: bad interpreter: No such file or directory 2、在Windows编辑的脚本导入Linux系统中,执行报错问题 yum install -y dos2unix 3、或者本地安装 rpm -ivh /mnt/Packages/dos...... 4、然…

【战略前沿】丹麦正在建造一台英伟达人工智能超级计算机

【原文】Denmark is building an Nvidia AI supercomputer 【作者】Linnea Ahlgren 它将于今年上线,并以新的量子计算软件为特色。 过去一年最大的赢家——芯片制造商英伟达(Nvidia)和制药制造商诺和诺德(Novo Nordisk&#xff0…

MCGS学习——用户管理

用户管理介绍 用户管理主要是为了实现触摸屏的安全操作,工业过程控制中,应该尽量避免由于人为的误操作所引发的故障或事故,而某些失误带来的后果是致命的;通过用户管理严格限制各类操作的权限,使不具备操作资格的人员…

LeetCode刷题日志-153.寻找旋转排序数组中的最小值

思路:总所周知二分的逻辑非常简单,难点在边界处理。这道题我说说自己的理解, 首先二分的根本是有序,只要有序就能二分,哪怕是部分有序(这个是重点!!) 我们先搞清楚题目中…

MyBatis:查询与连接池

一、查询 1、多表查询 尽量避免使用多表查询,尤其是对性能要求较高的项目。因为多表查询必然会导致性能变低。 例如:select *from ta运行需要10ms,select *from tb 运行也需要10s。但是,select *from ta left join tb on ta.xx…

【Web APIs】DOM节点

目录 1.节点操作 1.1DOM节点 1.2查找节点 1.2.1父节点查找 1.2.2子节点查找 1.2.3兄弟节点查找 1.3增加节点 1.4克隆节点 1.5删除节点 2.时间对象 2.1实例化 2.2时间对象方法 2.3时间戳 3.重绘和回流 1.节点操作 1.1DOM节点 DOM节点:DOM树中的每一个…