关于Spring事务及其传播机制

1496 篇文章 10 订阅
1494 篇文章 14 订阅

目录

  • 一丶Spring中事务的实现

  • <1>事务的四大特性有哪些<2>数据库并发一致性问题以及隔离级别的设置2>隔离可以解决的并发问题<3>Spring事务隔离级别

  • <1>事务的传播机制是什么?为什么需要传播机制<2>事务的传播机制有哪些?<3>Spring事务传播机制使用和各种场景演示1>支持当前事务(REQUIRED)2>不支持当前事务(REQUIRES_NEW)3> 不支持当前事务,NEVER 抛异常4>NESTED 嵌套事务 + 嵌套事务和加入事务区别?

这部分,就是关于事务了。emmmm,前言也不知道说啥了,人有点麻了。

还是老规矩,红色标题是重点。

一丶Spring中事务的实现

<1>MySQL中的事务使用(回顾)

事务在MySQL 有 3 个重要的操作:开启事务、提交事务、回滚事务,它们对应的操作命令如下:

 
 

-- 开启事务 start transaction; -- 业务执行 -- 提交事务 commit; -- 回滚事务 rollback;

这样写可能有点空洞,那么我们按照实际来:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

<2>手动操作事务

当前这种方式我们了解一下就行,我们主要使用是自动操作事务

Spring 手动操作事务和上面 MySQL 操作事务类似,它也是有 3 个重要操作步骤:

1.开启事务(获取事务)。

2.提交事务。

3.回滚事务。

SpringBoot 内置了两个对象, DataSourceTransactionManager 用来获取事务(开启事务)、提交或

回滚事务的,而 TransactionDefinition 是事务的属性,在获取事务的时候需要将TransactionDefinition 传递进去从而获得一个事务 TransactionStatus,实现代码如下:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

<3>自动操作事务

声明式事务的实现很简单,只需要在需要的方法上添加 @Transactional 注解 就可以实现了,无需手动

开启事务和提交事务,进入方法时自动开启事务,方法执行完会自动提交事务,如果中途发生了没有处理的异常会自动回滚事务,具体实现代码如下:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

此时我传值是true,所以这里会抛出一个异常

编辑切换为居中

添加图片注释,不超过 140 字(可选)

然后看一看我们的SQL数据库,也可以看到值没有修改

编辑切换为居中

添加图片注释,不超过 140 字(可选)

然后我们不让这个异常执行,也就是传一个false

编辑切换为居中

添加图片注释,不超过 140 字(可选)

可以看到此时修改成功

编辑切换为居中

添加图片注释,不超过 140 字(可选)

当然,除了这种做法,还有一种做法:配置一个声明式的AOP代理,拦截符合规则的方法,就可以自动的使用事务。

1>作用域说明

 
 

@Transactional 可以用来修饰方法或类: 修饰方法时:需要注意只能应用到 public 方法上,否则不生效。推荐此种用法。 修饰类时:表明该注解对该类中所有的 public 方法都生效。

但是!这里注意了,极其不推荐对类进行使用

2>参数说明

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

3>@Transactional 工作原理

@Transactional 是基于 AOP 实现的,AOP 又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现了接口,会使用 CGLIB 动态代理。

@Transactional 在开始执行业务之前,通过代理先开启事务,在执行成功之后再提交事务。如果中途遇

到的异常,则回滚事务。

@Transactional 实现思路预览:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

@Transactional 具体执行细节如下图所示:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

二丶事务隔离级别

<1>事务的四大特性有哪些

事务有4 大特性(ACID),原子性、持久性、一致性和隔离性,具体概念如下:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

上面 4 个属性,可以简称为ACID。

原子性(Atomicity,或称不可分割性)

一致性(Consistency)

隔离性(Isolation,又称独立性)

持久性(Durability)。

而这 4 种特性中,只有隔离性(隔离级别)是可以设置的。

那为什么要设置事务的隔离级别呢?

设置事务的隔离级别是用来保障多个并发事务执行更可控,更符合操作者预期的。

什么是可控呢?

比如近几年比较严重的新冠病毒,我们会把直接接触到确证病例的人员隔离到酒店,而把间接接触者(和直接接触着但未确诊的人)隔离在自己的家中,也就是针对不同的人群,采取不同的隔离级别,这种隔离方式就和事务的隔离级别类似,都是采取某种行动让某个事件变的“更可控”。而事务的隔离级别就是为了防止,其他的事务影响当前事务执行的一种策略。

<2>数据库并发一致性问题以及隔离级别的设置

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

注意一下,我这里是部分解决,不是全部解决。

1>隔离级别的解读

编辑切换为居中

添加图片注释,不超过 140 字(可选)

2>隔离可以解决的并发问题

编辑切换为居中

添加图片注释,不超过 140 字(可选)

<3>Spring事务隔离级别

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

这个我们之后具体实践的时候再细细讲

但是这里不妨碍我们先体现提一下

编辑切换为居中

添加图片注释,不超过 140 字(可选)

三丶事务的传播机制

<1>事务的传播机制是什么?为什么需要传播机制

Spring 事务传播机制定义了多个包含了事务的方法,相互调用时,事务是如何在这些方法间进行传递

的。

事务隔离级别是保证多个并发事务执行的可控性的(稳定性的),而事务传播机制是保证一个事务在多

个调用方法间的可控性的(稳定性的)。

<2>事务的传播机制有哪些?

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

<3>Spring事务传播机制使用和各种场景演示

1>支持当前事务(REQUIRED)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

这里可以看到我没有加注释,为什么呢?

因为REQUIRED是默认的隔离级别,如果也就是我们级别设置当中的

编辑

添加图片注释,不超过 140 字(可选)

2>不支持当前事务(REQUIRES_NEW)

看我下面的代码演示,就是修改了一个权限级别

编辑切换为居中

添加图片注释,不超过 140 字(可选)

然后发起请求,重新访问

编辑切换为居中

添加图片注释,不超过 140 字(可选)

先看一下执行结果

编辑切换为居中

添加图片注释,不超过 140 字(可选)

可以发现其实没有修改成功,为什么呢?看我们的执行流程

编辑切换为居中

添加图片注释,不超过 140 字(可选)

然后学的时候,我觉得我自己在这里的问题描述不是很清楚,所以我重新描述一下问题就应该能理解清楚了

编辑

添加图片注释,不超过 140 字(可选)

那么我们换种写法,把事务的开启挪一个地方

编辑切换为居中

添加图片注释,不超过 140 字(可选)

然后此时我们查看是否修改成功

编辑切换为居中

添加图片注释,不超过 140 字(可选)

这会又可以修改成功了,我们来看日志分析一下

编辑切换为居中

添加图片注释,不超过 140 字(可选)

3> 不支持当前事务,NEVER 抛异常

这个演示就很直接了,直接给你报错

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

4>NESTED 嵌套事务 + 嵌套事务和加入事务区别?

看我如下的代码演示,这个和上面的是有区别的熬,我这里两个方法同时给了嵌套注释,这是加入事务的演示

编辑切换为居中

添加图片注释,不超过 140 字(可选)

此时你可以看到,虽然说我都给了嵌套注释,但是这里其实和我上面的加入事务区别不是很大,为什么呢?往下走,继续往下看

编辑切换为居中

添加图片注释,不超过 140 字(可选)

此时数据库没有被修改,那么我们看看执行流程

编辑切换为居中

添加图片注释,不超过 140 字(可选)

是不是有点迷??没关系,我换种方式再演示一下,看看区别

这里我们设置回滚点

编辑切换为居中

添加图片注释,不超过 140 字(可选)

编辑切换为居中

添加图片注释,不超过 140 字(可选)

可以发现,很神奇的修改成功了

编辑切换为居中

添加图片注释,不超过 140 字(可选)

那么我们再来分析分析执行流程

编辑切换为居中

添加图片注释,不超过 140 字(可选)

现在是不是差不多看明白了?那么来语言总结一下

 
 

嵌套事务只所以能够实现部分事务的回滚,是因为事务中有一个保存点(savepoint)的概念,嵌套事务 进入之后相当于新建了一个保存点,而滚回时只回滚到当前保存点,因此之前的事务是不受影响的 而 REQUIRED 是加入到当前事务中,并没有创建事务的保存点,因此出现了回滚就是整个事务回滚,这 就是嵌套事务和加入事务的区别

所以

嵌套事务(NESTED)和加入事务(REQUIRED )的区别:

1.整个事务如果全部执行成功,二者的结果是一样的。

2.如果事务执行到一半失败了,那么加入事务整个事务会全部回滚;而嵌套事务会局部回滚,不会影

响上一个方法中执行的结果。

            资源获取:

大家点赞、收藏、关注、评论啦 、查看👇🏻👇🏻👇🏻微信公众号获取联系方式👇🏻👇🏻👇🏻

 精彩专栏推荐订阅:下方专栏👇🏻👇🏻👇🏻👇🏻

每天学四小时:Java+Spring+JVM+分布式高并发,架构师指日可待

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值