浅谈 @Transtational 原理 及其失效场景(1)

news2024/9/23 17:16:09

上篇讲述了 当@Transtctional遇到@Async遇碰撞出怎样的火花? 本篇则主要从@Transtational出发仔细谈谈。

一、调用场景复现,代码层面什么情况会失效?

1)同类操作:事物A调取非事物B,A报错/B报错(事物生效)

@Transactional(rollbackFor = Exception.class)
	@Override
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		this.saveInspectInfoB();
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
	}

	public void saveInspectInfoB() {
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
	}

在这里插入图片描述
结果:回滚

@Transactional(rollbackFor = Exception.class)
	@Override
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		this.saveInspectInfoB();

	}

	public void saveInspectInfoB() {
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
	}

结果:回滚 和代码顺序无关

2)同类操作:非事物A调取事物B,A报错/B报错(事物失效)

2-1)报错逻辑放最后一层

@Override
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		this.saveInspectInfoB();

	}

	@Transactional(rollbackFor = Exception.class)
	public void saveInspectInfoB() {
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
	}

结果:由于报错在最后,所以都执行成功;

2-2)报错逻辑放中间

@Override
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		this.saveInspectInfoB();

	}

	@Transactional(rollbackFor = Exception.class)
	public void saveInspectInfoB() {
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
	}

在这里插入图片描述
结果:报错之前的都执行成功;之后的都未执行;

这种情况则是最常用的一种失效的场景。

3)非同类操作:事物A调取非事物B,A报错/B报错(事物生效)

@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		asyncTestService.saveInspectInfoB();
	}
public void saveInspectInfoB() {
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
	}

结果:回滚 和代码顺序无关

@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		asyncTestService.saveInspectInfoB();
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
	}
public void saveInspectInfoB() {
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
	}

结果:回滚 和代码顺序无关

4)非同类操作:非事物A调取事物B,A报错

@Override
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
		asyncTestService.saveInspectInfoB();
	}
@Transactional(rollbackFor = Exception.class)
	public void saveInspectInfoB() {
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
	}

事物只对B里的代码有效,A毫无关系,只是一个单纯的调用者。
这种使用情况是有问题的,更新插入操作一起才能有事物一致性的概念。

5)非同类操作:非事物A调取事物B,B报错

@Override
	public void saveInspectInfoA() {
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
		asyncTestService.saveInspectInfoB();
	}
@Transactional(rollbackFor = Exception.class)
	public void saveInspectInfoB() {
		//回滚
		TaskInspect taskInspect = new TaskInspect();
		taskInspect.setProject("sss");
		//事物操作方法2
		taskInspectMapper.insertSelective(taskInspect);
		//事物操作方法3
		taskInspectMapper.updateDataStatus(126389155885236224L);
	}

B代码失败,对应的B方法里的回滚,A不影响。

二、调用场景复现,代码层面 话语总结

我们通过四种情况发现:

1)事物A调取非事物B,不在乎B方法在同类还是非同类,反正其代码是附属于A的,所以这种情况 事物都是生效的。

2)非事物A调取事物B,B必须在非同类里,非事物A则主要是写一些查询类的逻辑,涉及到数据库的,必须保证是在方法B中。

3)事物B中再次调取异步方法除外,无关紧要或者用实物同步器实现。

三、源码解析,到底是如何回滚的?

1)@Transactional 注解

@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD})
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Inherited
@java.lang.annotation.Documented
public @interface Transactional {
	//别名,和transactionManager一样
    @org.springframework.core.annotation.AliasFor("transactionManager")
    java.lang.String value() default "";
	//事务管理器,Spring事务支持使用多个事务管理器,可以通过该属性使用指定事务管理器
    @org.springframework.core.annotation.AliasFor("value")
    java.lang.String transactionManager() default "";

    java.lang.String[] label() default {};
    //事物传播方式 默认为:Propagation.REQUIRED(支持当前事务,如果当前没有事务,就新建一个事务)
    org.springframework.transaction.annotation.Propagation propagation() default org.springframework.transaction.annotation.Propagation.REQUIRED;
	//事务的隔离级别,默认值是 Isolation.DEFAULT,即数据库设定的隔离级别
    org.springframework.transaction.annotation.Isolation isolation() default org.springframework.transaction.annotation.Isolation.DEFAULT;

    int timeout() default -1;
	//事务超时时间,默认为数据库设定的时间
    java.lang.String timeoutString() default "";
	//事物可读
    boolean readOnly() default false;
    //设定要回滚事务的异常类,当捕获到这些异常时回滚,否则不回滚
    java.lang.Class<? extends java.lang.Throwable>[] rollbackFor() default {};
	//设定要回滚事务的异常类名称,当捕获到这些异常时回滚,否则不回滚。
    java.lang.String[] rollbackForClassName() default {};
	//设定不回滚事务的异常类,当捕获到这些异常时不回滚
    java.lang.Class<? extends java.lang.Throwable>[] noRollbackFor() default {};
	//设定不回滚事务的异常类名称,当捕获到这些异常时不回滚
    java.lang.String[] noRollbackForClassName() default {};
}

@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD}) :表明注解可以应用于方法和实体类上。
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME):表明应该在运行时保留。

2)事物传播方式 Propagation

传播方式说明
REQUIRED当前有事务时沿用现有事务,无事物则新建一个事物
SUPPORTS当前有事务时沿用现有事务,无事物则不使用事务
MANDATORY当前有事务时沿用现有事务,当前有事务时沿用现有事务
REQUIRES_NEW当前有事物,挂起;创建新事物
NOT_SUPPORTED当前有事物,挂起;不使用事物
NEVER
NESTED

3)事物隔离级别 isolation

隔离级别中文说明
DEFAULT默认值默认数据库设定的隔离级别
READ_UNCOMMITTED读未提交最低的隔离级别,一个事务可以读取另一个事务未提交的数据。可能会导致脏读、幻读或不可重复读
READ_COMMITTED读已提交
REPEATABLE_READ可重复读
SERIALIZABLE可串行化

数据库默认的隔离级别是:
查看命令:SELECT @@SESSION.TRANSACTION_ISOLATION;

在这里插入图片描述

4)TransactionManager事物管理器

5)从Debug出发,大概查看整个执行流程

Controller调取Service生成代理类忽略,直接从实现层加入事物注解谈起。
在这里插入图片描述
在这里插入图片描述
我们可以看到,通过spring CGLIB生成了一个代理类 sig2.
在这里插入图片描述
在这里插入图片描述
直接新建一个CglibMethodInvocation.详情见细节。
在这里插入图片描述
直接走到父类的执行方法里。拦截器直接调用Invoke
在这里插入图片描述
在这里插入图片描述

我们会发现,拦截器里有多个实现类,我们的目标实现肯定也在其中。

在这里插入图片描述

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

最终走到了TransactionAspectSupport,核心在这。
在这里插入图片描述
创建一个新事物,只有事物传播方式满足条件的,才会走创建逻辑。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
点击obtainDataSource().getConnection(); 我们会发现有好多的连接方式,这点在哪里配置的呢?回头去看一眼配置文件配置的什么呢?
在这里插入图片描述

在这里插入图片描述
根据需要初始化事物同步。
在这里插入图片描述
在这里插入图片描述
至此一层流程到此结束。

四、try-catch会影响事物执行吗?

1)try catch只是对异常是否可以被@Transactional 感知 到有影响。如果错误抛到切面可以感知到的地步,那就可以起作用。

从demo入手,大家会发现,@Transactional(rollbackFor = Exception.class),直接配置了回滚异常类。Exception.class

@Transactional(rollbackFor = Exception.class)
	public void saveInspectInfoB() {
		try {
			//事物操作方法3
			taskInspectMapper.updateDataStatus(126389155885236224L);

			this.saveInspectInfoC();
			//回滚
			TaskInspect taskInspect = new TaskInspect();
			taskInspect.setProject("sss");
			//事物操作方法2
			taskInspectMapper.insertSelective(taskInspect);
		}catch (Exception e){
			throw new BizException(e);
		}
	}

	public void saveInspectInfoC(){
		//事物操作方法1
		taskInspectMapper.updateDataStatus(126387703699750912L);
	}

我们有rollbackFor,且用了try catch,试问会回滚吗?
在这里插入图片描述
在这里插入图片描述
答案是:会回滚
在这里插入图片描述
这种情况呢?会怎样?
在这里插入图片描述
在这里插入图片描述
catch住了,无报错信息。回滚失败,这是为何呢?通俗理解即可,本来我的rollbackFor时刻盯着是否报错呢,结果你中间catch插进来了,相当于最开始两个人传话,后来中间又加了一个人,那么如果中间这个人如实告知,当一个很好的传声筒,那就不会有问题,假如他接收了第一个人的信息,结果却没告诉第三个人,那么信息肯定就中断了,我并不知道到底发生了什么。

2)对于@Transactional可以保证RuntimeException错误的回滚,如果想保证非RuntimeException错误的回滚,需要加上rollbackFor = Exception.class 参数。

在这里插入图片描述
在这里插入图片描述
方法A单纯的加了事物注解,方法B也加了事物注解,且rollbackFor了。

在这里插入图片描述
结果是:回滚。

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

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

相关文章

流体力学解迷宫

诶&#xff0c;我手机呢&#xff1f;我手机放哪了&#xff1f;我手机是不是落餐厅了&#xff1f;会议室&#xff1f;厕所&#xff1f; 最近脑子有点不好使&#xff0c;可能需要练一练……解解迷宫吧 怕脑子吃不消&#xff0c;从简单的开始&#xff0c;不错&#xff0c;轻松拿…

EEtrade:黄金首饰是不是越软越好

黄金一直以来都是人们喜爱的贵金属之一。许多人在购买黄金首饰时&#xff0c;常常会关注黄金的纯度和硬度。那么&#xff0c;黄金首饰是不是越软越好呢?本文将详细探讨这个问题&#xff0c;并分析黄金首饰的硬度与其使用和美观性的关系。 黄金的纯度与硬度 黄金纯度 黄金的…

Linux系列之基础篇

文章目录 开篇明义基础篇实际操作篇高级篇Linux之JavaEELinux在哪些地方使用Linux应用领域 Linux入门基本介绍Linux和Unix关系 VM和Linux的安装基本说明安装VM17.5安装Centos7.6网络连接解释 虚拟机克隆虚拟机快照虚拟机迁移和删除安装vmtools设置共享文件夹 Linux目录结构 开篇…

屏幕翻译app下载哪个?高效学习工作必备

新学期即将开始&#xff0c;无论是线上学习还是筹备假期的海外交流&#xff0c;面对满屏的外文资料&#xff0c;一款得心应手的屏幕翻译软件成为必备利器。 幸运的是&#xff0c;现在有许多免费且功能强大的屏幕翻译工具&#xff0c;能够让你的学习与旅行更加顺畅。 以下是五…

Win7 配置Oracle 11G R2、PLSQL Development、添加用户名、远程访问数据库

本教程所有操作均在VMWare虚拟机上操作&#xff0c;Oracle这种又难装、又难卸、污染性这么大的程序&#xff0c;怎么会让他出现在我的生产环境中呢&#xff1f;自己在虚拟机上新建了一个Win7_x64的系统&#xff0c;进行Oracle安装测试。 1.Oracle文件的获取 网上有很多下载这…

LabVIEW便携涡流检测系统开发

针对便携式脉冲涡流检测系统的开发需求&#xff0c;使用LabVIEW进行软件设计与实现。系统需要集成对铁磁性和非铁磁性材料的检测功能&#xff0c;并提供友好的用户界面&#xff0c;便于操作与数据读取。 硬件选型&#xff1a; 脉冲涡流主机&#xff1a; 选择理由&#xff1a; …

【Liunx入门】Liunx换源

文章目录 前言一、备份默认源文件1.配置文件路径2.备份源文件 二、换源1.查看Ubuntu版本2.镜像源地址1&#xff09;清华源2&#xff09;阿里源3&#xff09;中科大源 3.换源 三、更新镜像源总结 前言 由于Liunx系统默认的下载源为国外的源&#xff0c;所以在国内下载资源比较慢…

1+X 职业技能等级证书面向哪些人群介绍

日前&#xff0c;“大数据应用开发&#xff08;Python&#xff09;”职业技能等级证书已开放面向社会人员招生。 什么是1X职业技能等级证书&#xff1f; “1” 学历证书&#xff0c;代表专业&#xff0c;即学历、毕业 “X” 若干职业技能等级证书&#xff0c;是根据…

虫情系统的重要作用

在农业生产、林业管理和生态保护的广阔领域中&#xff0c;虫情监测系统如同一双锐利的眼睛&#xff0c;时刻关注着农田中的细微变化&#xff0c;为农作物的健康生长保驾护航。这一系统的引入&#xff0c;不仅标志着农业管理向智能化、准确化迈出了重要一步&#xff0c;更在提升…

vue postcss postcss-pxtorem 页面自适应 动态

vue postcss postcss-pxtorem 页面自适应 动态 postcss-pxtorem实现页面自适应1、安装postcss-pxtorem2、根目录创建postcss.config.js&#xff0c;并配置以下内容3、创建rem.js&#xff0c;动态设置root px4、在main.js中引入rem.js5、在main.js中创建全局处理函数px2rem6、对…

上海亚商投顾:沪指震荡微涨 固态电池、折叠屏概念股集体大涨

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日窄幅震荡&#xff0c;黄白二线分化明显&#xff0c;微盘股指数涨超2.5%&#xff0c;题材概念较为活跃…

【渗透测试】ATTCK靶场一,phpmyadmin,域渗透,内网横向移动攻略

前言 博客主页&#xff1a;h0ack1r丶羽~ 从0到1~ VulnStack&#xff0c;作为红日安全团队匠心打造的知识平台&#xff0c;其独特优势在于全面模拟了国内企业的实际业务场景&#xff0c;涵盖了CMS、漏洞管理及域管理等核心要素。这一设计理念源于红日安全团队对ATT&CK红队评…

VBA之正则表达式(47)-- 快速将公式转换为静态值计算

实例需求&#xff1a;工作表I列包含多种计算公式&#xff0c;为了便于演示&#xff0c;将I列公式显示在J列单元格中&#xff0c;现在需要将公式的单元格引用转换为静态值&#xff0c;如K列所示。 示例代码如下。 Sub RegExpDemoReplace()Dim Res()Dim objRegEx As ObjectDim o…

零基础5分钟上手亚马逊云科技-NLP文字理解AI服务

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我会每天介绍一个基于亚马逊云科技…

android gradle 配置国内gradle地址

1. 地址&#xff1a; 腾讯云镜像 Gradle下载地址&#xff1a;https://mirrors.cloud.tencent.com/gradle/ 阿里云镜像 Gradle下载地址&#xff1a;https://mirrors.aliyun.com/macports/distfiles/gradle/ 阿里云镜像 Gradle下载地址&#xff1a;https://mirrors.aliyun.com…

Python酷库之旅-第三方库Pandas(102)

目录 一、用法精讲 441、pandas.DataFrame.mask方法 441-1、语法 441-2、参数 441-3、功能 441-4、返回值 441-5、说明 441-6、用法 441-6-1、数据准备 441-6-2、代码示例 441-6-3、结果输出 442、pandas.DataFrame.query方法 442-1、语法 442-2、参数 442-3、功…

【C++题解】1223. 汉诺塔的移动次数

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1223. 汉诺塔的移动次数 类型&#xff1a;函数、递归基础 题目描述&#xff1a; 汉诺塔的问题大家都已经很熟悉了&#xff0c;有三个柱子&#xff0c;每个柱子上有一些大小不一的金…

Python(C)图像压缩导图

&#x1f3af;要点 傅里叶和小波变换主成分分析彩色图压缩制作不同尺寸图像K均值和生成式对抗网络压缩无损压缩算法压缩和解压缩算法离散小波变换压缩树结构象限算法压缩矩阵分解有损压缩算法量化模型有损压缩算法JPEG压缩解压缩算法 Python图像压缩 图像压缩可以是有损的&…

Gazebo Harmonic gz-harmonic 和 ROS2 Jazzy 注意事项

激光显示 点呈现 射线呈现 rviz2 新旧版本并存的混乱 本教程旨在为在Ubuntu Jammy&#xff08;最新支持Gazebo Classic包的Ubuntu版本&#xff09;上运行Gazebo Classic&#xff08;如Gazebo 11&#xff09;的用户提供指导&#xff0c;这些用户计划将其代码迁移到新的Gazebo版…

大语言模型(LLMs)全面学习指南

大语言模型&#xff08;LLMs&#xff09;作为人工智能&#xff08;AI&#xff09;领域的一项突破性发展&#xff0c;已经改变了自然语言处理&#xff08;NLP&#xff09;和机器学习&#xff08;ML&#xff09;应用的面貌。这些模型&#xff0c;包括OpenAI的GPT-4o和Google的gem…