运维.售后
论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
博客
Blog
ToB门户
了解全球最新的ToB事件
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
ToB企服应用市场:ToB评测及商务社交产业平台
»
论坛
›
软件与程序人生
›
后端开发
›
Java
›
Spring事务传播机制
Spring事务传播机制
一给
金牌会员
|
2024-4-6 09:16:35
|
显示全部楼层
|
阅读模式
楼主
主题
871
|
帖子
871
|
积分
2613
1.Spring对事物的支持一般有两种方式
编程式事务管理:通过 TransactionTemplate或者TransactionManager手动管理事务,实际应用中很少使用,这不是本文的重点,就不在这里赘述。
声明式事务管理:使用场景最多,也是最推荐使用的方式,直接加上@Transactional注解即可。
2.Transactional注解几大参数解释
@Transactional 注解是用于声明事务性方法的注解,通常用于标记在服务层的方法上。该注解提供了一些参数,用于配置事务的一些属性。以下是几个常用的参数及其解释:
propagation(传播行为):
- 用于指定事务的传播行为。包括诸如 `REQUIRED`、`REQUIRES_NEW`、`SUPPORTS`、`NOT_SUPPORTED` 等。该参数定义了方法被嵌套调用时,事务如何传播。
2. isolation(隔离级别):
- 用于指定事务的隔离级别。包括 `DEFAULT`、`READ_UNCOMMITTED`、`READ_COMMITTED`、`REPEATABLE_READ`、`SERIALIZABLE`。该参数定义了事务处理过程中对数据的隔离程度。
3. readOnly(只读):
- 用于指定事务是否是只读的。如果设置为 `true`,表示只读取数据而不修改,可以优化事务处理。默认值为 `false`。
4. timeout`(超时时间):
- 用于指定事务的超时时间,单位为秒。如果事务执行时间超过指定的时间,则会被强制回滚。默认值为 `-1`,表示没有超时限制。
5. rollbackFor` 和 noRollbackFor:
- 用于指定在哪些异常情况下回滚事务。`rollbackFor` 指定哪些异常时回滚,`noRollbackFor` 指定哪些异常时不回滚。可以传入异常类型的数组
重点讲解propagation(传播行为)
七大参数设置:
场景:
假设有这样的场景 有A类和B类 A类内部有一个事务方法 B类有一个事务方法
class A{
public B b;
@Transactional
public void a(){
//1.对数据表A进行插入操作方法
System.out.println("往A插入数据");
//2.对数据表B进行插入操作方法
b.b();
//
System.out.println("往A继续插入数据");
}
}
class B{
@Transactional
public void b(){
//对数据库进行插入操作方法
System.out.println("更新表单 插入数据");
}
}
复制代码
这种是一种常见的嵌套事务 如果都存在事务可能它的SQL是这样的
BEGIN
UPDATE A;
-- B类的事务来了
BEGIN
UPDATE B;
COMMIT;
--
UPDATE A;
COMMIT;
复制代码
这种写法在MYSQL是不支持的,如果执行了B事务那么A的部门事务失效。如果想要实现这两个事务都存在怎么办?那我们可以直接把B事务的BEGIN和COMMIT去掉 让B事务融入到A事务中即可。
BEGIN
UPDATE A;
-- B类的事务来了
UPDATE B;
--
UPDATE A;
COMMIT;
复制代码
这种情况其实就代表了传播行为的
REQUIRED
传播行为
具体来说,当一个方法使用 @Transactional(propagation = Propagation.REQUIRED) 进行标记时,它的行为如下:
存在事务时: 方法将在当前事务中运行,与调用该方法的外部事务合并为一个事务。
不存在事务时: 方法将启动一个新的事务。
这种情况会出现一个问题 就是外部的事务融入到当前事务中的时候如果出错那么整个事务都会进行回滚。
解决这种情况有一个名词叫
挂起
挂起解释就是使用其他线程获取不同的数据库连接 如果执行两个不同的事务 这样就不会影响原本事务的流程。
-- 线程1获取到数据库连接1 执行A事务的流程
BEGIN
UPDATE A;
-- B类的事务来了 线程2获取到数据库连接2 执行B事务的流程
BEGIN
UPDATE B;
COMMIT;
-- 执行后 重新将线程B切换到线程A 来执行后续流程
UPDATE A;
COMMIT;
复制代码
这种情况也是传播行为中的
REQUIRES_NEW
传播行为
具体来说,当一个方法使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 进行标记时,它的行为如下:
存在事务时: 方法将挂起当前的事务,并启动一个新的事务。在该方法执行完毕后,新事务将被提交或回滚,然后恢复挂起的事务。
不存在事务时: 方法将启动一个新的事务。
还有一种情况就是嵌套事务,MySQL是不支持嵌套事务的,但Mybatis在这个层面加入了保存点和回滚点来支持。
BEGIN
UPDATE a set score=100 where id=1;
Savepoint a;
update b set score=200 where id=2;
ROLLBACK to a;
-- 如果B事务出现问题 不会影响后面的事务
UPDATE a set score=300 where id=3;
COMMIT;
复制代码
当一个方法使用 @Transactional(propagation = Propagation.NESTED) 进行标记时,它的行为如下:
存在事务时: 方法将在一个嵌套事务中运行。如果当前存在事务,则将创建一个新的保存点,并在方法执行时将该保存点设为当前事务的回滚点。如果方法执行后,嵌套事务回滚,则只会回滚到该保存点,而不会影响外部事务。
不存在事务时: 方法将启动一个新的事务,行为与 REQUIRED 类似。
上面三种情况其实就能解决掉百分之99%的事务嵌套问题,Spring为我们提供了七个事务传播行为,解释后四个
SUPPORTS:支持当前事务,B事务设置了这个传播行为,如果A有事务就融入到A事务中,如果没有就不开启事务,这个使用场景适用于只读和只有多SELECT场景下。
MANDATORY:只支持当前事务,B事务如果设置了这个传播行为,那么它必须要被传入到一个有事务的方法中,不然就会抛出异常。
NOT_SUPPORTED:不支持事务,如果B事务设置了这个传播行为,那么它如果被传入到A事务方法内,那么它会将A事务进行挂起已非事务的方法来运行。
NEVER:不支持事务,只要有事务运行,就直接抛出异常。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
使用道具
举报
0 个回复
正序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
发新帖
回复
一给
金牌会员
这个人很懒什么都没写!
楼主热帖
手把手教你如何使用kali破解wifi密码( ...
3.2操作系统(基本分页存储管理的基本 ...
C++面试八股文:std::array如何实现编 ...
零基础入门 Java 后端开发,有哪些值得 ...
嵌入式 Linux 内核驱动开发【The first ...
上古神兵,先天至宝,Win11平台安装和配 ...
Wireshark学习笔记(一)常用功能案例 ...
你真的了解二叉树吗?(上篇) ...
软件开发中,如何为你的代码构建三层防 ...
SpringBoot(15)ORM ( Object Relatio ...
标签云
存储
服务器
快速回复
返回顶部
返回列表