当前位置: 首页 > news >正文

String 事务

目录

一、什么是事务

二、Spring事务的实现方式

1、编程式事务

2、声明式事务

三、自动操作事务的注解的三个属性

1、rollbackFor

2、isolation

3、propagation


前言:本文所见围绕的主题是事务,所以笔者先讲解什么是事务,先让大家了解事务,接着讲解在Spring中,如何对事务进行的实现,有两种方式,先讲手动创建的方式,再根据手动引出自动的方式,自动的方式是根据注解实现的,最后围绕注解再展开几个知识点~

一、什么是事务

例子:我们在王者荣耀里面充钱买皮肤这个行为,会包含几个操作:先充钱,再花钱购买皮肤,购买之后皮肤到达背包中,这几个操作缺一不可,如果你不充钱,就可以得到一个皮肤,腾讯怎么盈利?如果花了钱,却得不到皮肤,我们就白花钱了。。

我们进行的这一系列操作就是一个事务,事务具有原子性,要么这一组操作全部成功,要么全部失败~

那现在咱们知道了什么是事务,现在看一下,事务是如何操作的:

事务的操作主要有三步:
1. 开启事务:start transaction/ begin (⼀组操作前开启事务)
2. 提交事务: commit (这组操作全部成功, 提交事务)
3. 回滚事务: rollback (这组操作中间任何⼀个操作出现异常, 回滚事务)

在MySQL中我们学了事务了,对事物的应用不仅存在于数据库中,它可以遍布在生活中的各处,比如上述例子中的买皮肤,还要银行转账,商场买东西等等,所以它可以存在于Spring中,下面咱们来看看在Spring中,它是如何实现的~

二、Spring事务的实现方式

在Spring中一共有两种实现方式:1:编程式事务 2:声明式事务,第一种是手写代码去操作事务,第二种是通过注解自动操作事务。

1、编程式事务

通过代码操作事务,需要引入引入两个对象:DataSourceTransactionManager(事务管理器) 和 TransactionDefinition(事务属性)

进行以下操作:

开启事务:

TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);

提交事务:

dataSourceTransactionManager.commit(transactionStatus);

回滚事务:

dataSourceTransactionManager.rollback(transactionStatus);

完整的代码:

@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
@Autowired
private UserService userService;public String registry(String name,String password){// 开启事务TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);//业务逻辑 用户注册userService.registryUser(name,password);//提交事务dataSourceTransactionManager.commit(transactionStatus);//回滚事务//dataSourceTransactionManager.rollback(transactionStatus);return "注册成功";
}

使用编程式事务太麻烦了,下面咱们看看使用注解的方式

2、声明式事务

使用@Transactional注解,就可以自动开启事务,自动提交事务,当抛出异常后,自动回滚事务,注意:只有当抛出异常时,才会回滚,不管方法里面是否报错,因为报了错,在内部可以捕获,当然,如果没有报错,也想回滚,可以手动抛出异常~

@Autowired
private UserService userService;@Transactional
public String registry(String name,String password){//⽤⼾注册userService.registryUser(name,password);return "注册成功";
}
@Autowired
private UserService userService;@Transactional
public String registry(String name,String password){//⽤⼾注册userService.registryUser(name,password);log.info("⽤⼾数据插⼊成功");//对异常进⾏捕获try {//强制程序抛出异常int a = 10/0;}catch (Exception e){// ⼿动回滚事务TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return "注册成功";
}

大概介绍一下 @Transactional注解吧

  • 可以修饰public方法
  • 它也可以修饰类,表明类下面的所有的public方法都可以自动操作事务;

三、自动操作事务的注解的三个属性

@Transcactional注解它有三个重要的属性:

rollbackFor,它是异常回滚属性,能够指定当方法抛出什么类型的异常,进行自动回滚操作。

Isolation,它用来设置事务的隔离级别。

propagation,它用来设置事务的传播机制。

1、rollbackFor

@Transcactional默认当抛出运行时异常和产生错误时,才会进行自动回滚,如果想要抛出其他类型异常,比如IOException异常也想回滚,就可以利用rollbackFor属性,设置值,rollbackFor = Exception.class,就可以只要抛出异常,不管什么类型,都可以回滚~

@Autowired
private UserService userService;@Transactional(rollbackFor = Exception.class)
public String registry(String name,String password) throws IOException {//⽤⼾注册userService.registryUser(name,password);log.info("⽤⼾数据插⼊成功");if(true) {throw new IOException();}return "注册成功";
}

2、isolation

isolation可以设置隔离级别,先介绍一下事务隔离级别的概念,然后在介绍SQL中分别有几种级别,详细介绍一下这几种级别,最后介绍Spring中的隔离级别~

概念:

事务隔离指的是:当多个事务并发进行时,他们之间进行相互隔离

事务隔离程度指的是:事务在读取和修改数据时能够接触和修改其他事务所作的修改的程度

事务隔离的目的是确保事务进行并发进行时,能够正确执行,保证数据的一致性和可靠性,因为在一个并发环境中,多个事务同时进行时,可能同时修改和读取某些数据,如果不进行隔离,可能会产生一些问题,比如脏读,不可重复读,幻读。

SQL中事务的隔离级别(由低到高开始介绍):

  • 1、读取未提交(Read Uncommitted)

在该隔离级别下的事务可以看到其他事务未提交的数据,在这种级别下,如果某个未提交的数据,发生了回滚,但是有事务读取了,会造成脏读的问题,读取的这种数据叫做脏数据。(这是最低的隔离级别,并发性高,但是可靠性较差)

  • 2、读取已提交(Read Committed)

在该隔离级别下,事务可以读取其他事务已经提交的数据,这解决了脏读的问题,但是某个事物若进行多次重复的sql查询,可能会得到不同的结果,这可能会造成不可以重复读的问题

  • 3、可重复读(Repeatable Read)(MySQL中默认的事务隔离级别)

在该隔离级别下,在并发时,某个事物不会读到其他事物修改的数据,这就保证了数据的一致性,解决了不可以重复读的问题,但是又可能会造成幻读的问题,因为每次查询的都是同一组数据,有可能有事务在某一行插入了数据,但是我查询不到,我也就想在那一行插入插入,但是一直插入失败,这种现象叫做幻读。

  • 4、串行化(Serializable)

由于采用上述三种隔离级别,都可能会产生问题,所以使用串行化,会解决这些问题,因为这种是一个事务一个事务的进行,谁也根本干扰不到谁~ 但是这种级别性能太低,一般不会采取的~

Spring中的事务隔离级别:

一共有五种,多了一个DEFAULT级别,这个级别表示,当前连接的数据库是用的哪种隔离级别,就用哪种隔离级别~

Isolation.DEFAULT : 以连接的数据库的事务隔离级别为主
Isolation.READ_UNCOMMITTED:读未提交,对应SQL标准中 READ UNCOMMITTED
Isolation.READ_COMMITTED:读已提交,对应SQL标准中 READ COMMITTED
Isolation.REPEATABLE_READ:可重复读,对应SQL标准中 REPEATABLE READ
Isolation.SERIALIZABLE:串⾏化,对应SQL标准中 SERIALIZABLE
@Transactional(isolation = Isolation.READ_COMMITTED)

3、propagation

学会用这个属性,要先了解事务传播机制

要说传播,肯定是发生在多个实体之间,否则怎么能传播呢?

在Spring中事务可以用注解@Transactional声明方法,事务现在为方法服务,但是现在如果一个事务方法被另一个事务方法调用,那被调用的方法使用哪个事务呢?该怎么进行事务呢?这就用到了事务传播机制~ 一共有七种

现在有两个方法,一个是调用者,一个是被调用者,上图中的当前事务指的是调用者这个方法所用的事务

通过使用propagation属性,使用上面的值,可以指定传播方式

现在咱们重点讲解两种传播机制:REQUIRED(默认值)和REQUIRES_NEW

  • REQUIRED:被调用的方法如果使用的是这个传播机制,那么在被调用后,如果在调用者的方法使用了事务,那么被调用的方法使用对方的事务,如果调用者没有事务,则创建一个新的事务,共同使用~

特点:如果一个方法抛出了异常,那么所有参与其中的方法都会执行失败,发生回滚,因为所有方法使用的是同一个事务呀,要么同时成功,要么同时失败,这会保证数据的一致性~

  • REQUIRES_NEW:被调用的方法使用这个传播机制,那么被调用后,会创建新事务,不会使用对方的事务,互不干扰

 最后展示两个事务传播吧 :never和nested

  • never:使用了这种事务的传播后,被调用后,不允许调用者有使用事务,如果有,就抛出异常
  • nested:使用了这种事务传播后,被调用后,会使用调用者事务的子事务,子事务发生回滚,会使得父事务也发生回滚,并且如果还要其他方法也使用了父事务,也会连累其他方法执行失败~ 那该如何是好呢?可以只让当前的子事务的方法回滚,不影响父事务,怎么做的呢?在子事务的方法内,手动回滚。

那现在有个问题:nested和required的区别是什么?

使用nested会进行局部回滚,不会影响其他的事务发生回滚,而使用required不会局部回滚,一个事务回滚1,所有事物都要回滚,因为使用的是同一个事物。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 大模型面试系列-大模型算法工程师的面试题目与解答技巧详细说明
  • 安美数字酒店宽带运营系统 weather.php 任意文件读取漏洞复现
  • redis面试(十五)公平锁队列重排
  • 封装clickHouse线程池与ibeetl解析SQL并对结果转进行转化
  • 监控电脑屏幕被拍照的原理是什么?如此有趣的电脑防偷窥知识,你一学就会!
  • MAC 终端上传文件到云服务器
  • 【银河麒麟高级服务器操作系统】libtirpc-devel 安装问题分析
  • 英国与日本经济数据影响市场走势
  • allegro PCB设计心得笔记(四) -- 显示坐标原点和更改默认产品选项
  • 计算机网络——运输层(进程之间的通信、运输层端口,UDP与TCP、TCP详解)
  • Qt实现中英文切换中QMessageBox中的中文信息怎么处理
  • uniapp基础知识【搬代码】
  • vue播放flv视频流
  • ASP.NET Core Web API 使用Autofac框架
  • 内网穿透工具Cpolar 食用指南
  • Create React App 使用
  • Git同步原始仓库到Fork仓库中
  • Java小白进阶笔记(3)-初级面向对象
  • js 实现textarea输入字数提示
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • Phpstorm怎样批量删除空行?
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • storm drpc实例
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 爱情 北京女病人
  • 精彩代码 vue.js
  • 如何解决微信端直接跳WAP端
  • 实现菜单下拉伸展折叠效果demo
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 使用putty远程连接linux
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • nb
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 浅谈sql中的in与not in,exists与not exists的区别
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #单片机(TB6600驱动42步进电机)
  • (el-Date-Picker)操作(不使用 ts):Element-plus 中 DatePicker 组件的使用及输出想要日期格式需求的解决过程
  • (PySpark)RDD实验实战——取最大数出现的次数
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (搬运以学习)flask 上下文的实现
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (一)、python程序--模拟电脑鼠走迷宫
  • (一)基于IDEA的JAVA基础10
  • (转)linux 命令大全
  • (轉貼) UML中文FAQ (OO) (UML)
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .net 7 上传文件踩坑
  • .net 获取url的方法
  • .NET中统一的存储过程调用方法(收藏)
  • @selector(..)警告提示
  • [Algorithm][动态规划][路径问题][不同路径][不同路径Ⅱ][珠宝的最高价值]详细讲解
  • [BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)