【Spring事务学习】事务分类 隔离级别 事务传播机制

news2024/9/17 7:10:00

目录

需要知道:

🍑1、什么是事务?

🍑2、事务的主要操作3个

一、Spring中事务的实现方式

🍑1、编程式事务(手动写代码操作事务)(了解)

🍑2、声明式事务(用注解自动开启和提交事务)(重点)

(1)@Transactional注解的使用

(2)@Transactional 参数说明

(3)异常被捕获不会回滚的演示

(4)要求对于所有的异常都要求回滚的办法

二、事务的隔离级别(5种)

三、事务的传播机制

🍑1、事务的传播机制是什么?

🍑2、Spring中事务传播机制的分类(7种)

🍑3、 Spring 事务传播机制使用和部分场景演示 


需要知道:

🍑1、什么是事务?

将一组操作封装成⼀个执行(封装到一起),要么全部成功,要么全部失败。

比如转账分为两个操作:

(1):A账户+100元;

(2):B账户-100元;
如果没有事务,AB两个账户是分离的,当B账户给A转账成功,B账户少了100,但是A账户却没有反应;如果使用事务,那么AB两个账户的钱数是联动的,B账户给A转账少100元与A账户增加100元这个操作,是一起成功或者失败的。

🍑2、事务的主要操作3个

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


一、Spring中事务的实现方式

🍑1、编程式事务(手动写代码操作事务)(了解)

@Slf4j
@RestController
@RequestMapping("/trans")
public class TransactionController {
    @Autowired
    private UserService userService;
    //1、拿到事务管理器
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;
    //2、定义事务属性
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/addUser")
    public Integer addUser(String username,String password){
        //3、开启事务
        TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);
        //4、插入数据
        User user = new User(username,password);
        Integer result = userService.insert(user);
        log.info("影响的行数是:"+result);
        //5、提交事务
        dataSourceTransactionManager.commit(transaction);
        //6、回滚事务
//        dataSourceTransactionManager.rollback(transaction);
        return result;
    }

}

测试结果:(1)提交事务:url端传参,事务提交成功,数据库成功插入一条记录;

 (2)当回滚事务的时候,url端传参,数据库并没有插入数据。

🍑2、声明式事务(用注解自动开启和提交事务)(重点)

(1)@Transactional注解的使用

    /**
     * 自动提交事务
     */
@Slf4j
@RestController
@RequestMapping("/trans")
public class TransactionController {
    @Autowired
    private UserService userService;

    //声明式事务的实现很简单,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动
    //开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务;如果中途发⽣了没有处
    //理的异常会⾃动回滚事务
    @RequestMapping("/addUser2")
    @Transactional
    public Integer addUser2(String username,String password){
        //插入数据
        User user = new User(username,password);
        Integer result = userService.insert(user);
        //模拟异常
        int a = 10/0;
        return result;
    }
}

使用:

(1)声明式事务只要在需要的方法上添加@Transactional 注解就可以实现了;

(2)进入方法时自动开启事务,方法执行成功会自动提交事务;

(3)如果中途发生了没有处理的异常会自动回滚事务。默认在运行时异常和Error的时候才会回滚,也就是exception的子类中的RuntimeException会回滚。非运行时异常不回滚。

(4)如果异常被捕获,也不会进行处理;(后面演示)

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

(1)情况1:正常情况:使用注解@Transactional会自动开启和提交事务。url端传参,数据库添加数据成功。

(2)当有异常情况的时候,使用@Transactional会自动回滚事务,数据库也不会添加数据。

(3)当不使用注解@Transactional,但是有异常存在,数据依然会执行成功。

(2)@Transactional 参数说明

(3)异常被捕获不会回滚的演示

加一个被捕获的算数异常,观察结果:

/**
 * @Transactional 在异常被捕获的时候,不会进行回滚。
 */
@RestController
@RequestMapping("/trans")
public class TransactionController{
    @Resource
    private UserService userService;
    @RequestMapping("/addUser")
    @Transactional
    public Object addUser(String username,String password) {
        //插入数据
        User user = new User(username,password);
        Integer result = userService.insert(user);
        try {
            // 执⾏了异常代码(0不能做除数)
            int i = 10 / 0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return result;
    }
}

(4)要求对于所有的异常都要求回滚的办法

方式1:使用rollbackfor参数,指定对于所有异常都回滚。

@Transactional(rollbackFor = Exception.class)

方式2:手动回滚事务,在方法中使用TransactionAspectSupport.currentTransactionStatus() 可以得到当前的事务,然后设置回滚方法setRollbackOnly 就可以实现回滚了。

 // ⼿动回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

二、事务的隔离级别(5种)

1、Spring比MySQL的隔离级别多了一个default。

2、MySQL的默认隔离级别:可重复读;Oracle是读已提交。

3、Spring 中事务隔离级别只需要设置 @Transactional ⾥的 isolation 属性即可:

@Transactional(isolation = Isolation.SERIALIZABLE)

4、事务隔离级别解决的是多个事务同时调用一个数据库的问题。

​​​​​​​

5、Spring中事务隔离级别的分类

(1)Isolation.DEFAULT:以连接的数据库的事务隔离级别为主。
(2)Isolation.READ_UNCOMMITTED:读未提交,可以读取到未提交的事务,存在脏读。
(3)Isolation.READ_COMMITTED:读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重复读。
(4) Isolation.REPEATABLE_READ:可重复读,解决了不可重复读,但存在幻读(MySQL默认级别)。
(5) Isolation.SERIALIZABLE:串行化,可以解决所有并发问题,但性能太低。


举个栗子

(1)A和B正在写作业,B不想写,就照着A的作业抄,抄完之后B就开开心心的出去玩了,此时A检查发现了一个错误,就对错误进行了修正,那么B此时读到的就是错误的数据,这个现象就是“读未提交”,存在脏读问题;

(2)读已提交:A在写作业的过程中,给A上把锁,B不能抄,要等到A写完提交之后才能抄。那么当早上10.00A开始写作业,这个过程中B只能等着,10.30的时候A把作业写完了,B开始抄,等到10.40 A 又开始检查作业了,发现有问题,又开始修正,于是B抄作业,抄着抄着就突然发现数据变了。这就是出现了“幻读”现象。

脏读与不可重复读的区别:脏读是某一个事务读取了另一个事务未提交的脏数据,但是不可重复读是读取了前一事务提交的数据。

(3)可重复读:A在写作业的时候,B不能抄;B在抄作业的时候,A也不能修改。相当于A写作业的时候加了一个排它锁,B抄作业的时候加了一个共享锁,那么AB互不干扰。

(4)串行化:虽然B在抄作业的时候,A不能进行修改,但是A想着,闲着也是闲着,你抄语文作业,那么我就去修改数学作业,虽然没有直接修改B抄的作业,但是也影响到了B的最终的抄作业的效果,这就是出现了幻读现象。要用串行化来解决:也就是B抄语文作业,A所有的作业都不能修改,抄和写严格执行,不能相互响应。

三、事务的传播机制

🍑1、事务的传播机制是什么?

Spring 事务传播机制定义了多个包含了事务的方法,相互调用时,事务是如何在这些方法间进行传递的。事务传播机制是保证⼀个事务在多个调用方法间的可控性的(稳定性的)。

设置事务的传播机制:

@Transactional(propagation = Propagation.REQUIRED

事务传播机制解决的是⼀个事务在多个节点(方法)中传递的问题。

 🍑2、Spring中事务传播机制的分类(7种)

Spring中默认的传播机制是Propagation.REQUIRED。

​​​​​​​

🍑3、 Spring 事务传播机制使用和部分场景演示 

controller中代码


@RestController
@RequestMapping("/trans1")
public class UserLogController {
    @Autowired
    private UserService userService;
    @Autowired
    private UserLogService userLogService;
    //事务定义
    @Transactional
    @RequestMapping("/addUser1")
    public boolean addUser1(String username,String password){
        //插入用户表
        User user = new User(username,password);
        userService.insert(user);
        //插入用户日志表
        UserLog userLog = new UserLog(username);
        userLogService.insertLog(userLog);
        return true;
    }
}

(1)设置为Required

情况1:当两个都设置为Required,两个代码都正常,则两个都执行成功。

 情况2:对userlogService中添加一条异常,另一个userService中的代码正常不做修改,此时观察两个表的情况:

情况3:在userLogService对发生的异常自己进行捕获并回滚,另一个代码正常不做修改,观察是否会影响另一个userinfo表。 

 总结:

(1)两个代码要么一起执行成功;

(2)要么当有一个发生异常,两个就都进行回滚;

(3)就算对其中一个发生的异常进行捕获并回滚处理,也是两个都进行回滚。

 (2)设置为REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRES_NEW)

情况1:当两个代码都正常的时候,数据都插入成功。

 情况2:当有一个有异常的时候,不影响另一个。userLog表没有插入数据,userinfo表插入成功。

(3)设置为NEVER

给userLogService和userService都设置为NEVER级别,代码正常,也抛出异常。

@Transactional(propagation = Propagation.NEVER)

 (4)设置嵌套事务

@Transactional(propagation = Propagation.NESTED)

情况1:当userService和userLogService都正常的时候,执行成功。

情况2:当userLogService有异常的时候,都执行失败;

情况3:当userLogService有异常但是自动进行捕获并手动回滚的时候,uerLog表没有插入数据,但是userinfo表不受影响,数据插入成功。

🥰问题1:嵌套事务NESTED和加入事务REQUIRED有什么区别?

(1)共同点:整个事务如果全部执行成功,二者的结果是⼀样的。
(2)不同点:如果事务执行到一半失败了,那么REQUIRED事务整个事务会全部回滚;而嵌套事务NESTED会局部回滚,不会影响上⼀个方法中执行的结果。


🥰问题2:NESTED实现部分回滚的原因?

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


 和七月就要说再见啦~🥰

 

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

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

相关文章

【模型预测控制MPC】使用离散、连续、线性或非线性模型对预测控制进行建模(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

营销服一体化CRM有哪些?5款CRM系统对比

如今,一个成熟的CRM产品体系已从过去单点销售管理转变为营销、服务、交易的客户全旅程覆盖。那么在这个互联网信息化时代,面对海量的信息,用户很难快速准确地找到属于自己感兴趣的内容的,所以用户画像、兴趣标签变得越来越重要。 …

TCP三次握手和四次挥手以及11种状态(二)

11种状态 1、一开始,建立连接之前服务器和客户端的状态都为CLOSED; 2、服务器创建socket后开始监听,变为LISTEN状态; 3、客户端请求建立连接,向服务器发送SYN报文,客户端的状态变味SYN_SENT; 4、…

低代码在数智化时代中的应用

随着科技的发展,企业从生产到经营中海量的数据持续被记录。数据是望远镜,发现完全不同的商业边界;数据是显微镜,判断肉眼察觉不到的消费和生活行为;数据是雷达,帮助企业提前预测未来的行为。 而通过人工智…

红宝石阅读笔记

第七章 迭代器与生成器 7.3 生成器 乍一看理解,仔细想没理解,然后自己让n2,还原nTimes,等价于 function* nTimes() {if (true) {yield* (function* A() {if (true) {yield* (function* B() { })();yield 0;}})();yield 1;} } 最…

测试libcurl库的demo时,报错 curl_easy_perform() failed: SSL connect error

系统:麒麟V10 arm roothg-TR3250:/home/cur765/curl-7.65.3/docs/examples# cat /etc/os-release NAME"Kylin" VERSION"银河麒麟桌面操作系统(国防版)V10" VERSION_US"Kylin Linux Desktop (GFB)V10" IDkylin ID_LIKEdebian PRETT…

[虚幻引擎 MongoDB Client 插件说明] DTMongoDB MongoDB数据库连接插件,UE蓝图可以操作MongoDB数据库增删改查。

本插件可以在UE里面使用蓝图操作MongoDB数据库, 对数据库进行查询,删除,插入,替换,更新操作。插件下载地址在文章最后。 1. 节点说明 DT MongoDB | Client Create MongoDB Client - 创建客户端对象 创建一个 MongoDB 客…

MyBatis小记——逆向工程

目录 MyBatis 逆向工程的使用 使用逆向工程根据数据库中的表来生成对应的bean以及mapper 在当前工程根目录下创建一个mbg.xml文件 用来配置要生成的bean 和 mapper的信息 使用逆向工程的代码和逆向工程的配置文件来生成对应的bean和mapper 在org.westos.test 包下建一个类运…

7.31--Day01实战单体项目苍穹外卖

总结 今天回来在高铁上构想了一下,感觉大二有很多的事情要做,这个暑假还有一个月不能浪费了,回来最重要的事情就是看病了,身体一定要调养好了,大二的规划,大二上继续做省大创,需要做的有软件开…

rsync下行同步+inotify实时同步部署

目录 一、rsync简介 1.2 同步方式 1.2.1 全量备份 1.2.2 增量备份 1.2.3 差量备份 1.3 rsync的特点 1.4 rsync的优势与不足 1.5 rsync与cp、scp对比 1.6 rsync同类服务 二、rsync源服务器的关系 三、配置rsync源 3.1 基本思路 3.2 配置文件rsyncd.conf 3.3 独立…

每个团队都应该跟踪的 5 个销售指标

销售是一项极具挑战性的任务,需要综合运用各种技能,包括沟通、说服和谈判。销售人员不仅要对自己的产品了如指掌,还要深入了解他们的潜在客户。 因此,如果你的企业有销售部门,并且正在积极寻求、开启和完成销售&#…

商城免费搭建之java商城 开源java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c

 1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Re…

I.MX6ULL_Linux_驱动篇(41)platform设备驱动框架

我们在前面几章编写的设备驱动都非常的简单,都是对IO进行最简单的读写操作。像I2C、SPI、 LCD 等这些复杂外设的驱动就不能这么去写了, Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的软件思路,在这个思路下…

Jetson Nano之ROS入门 -- YOLO目标检测与定位

文章目录 前言一、yolo板端部署推理二、目标深度测距三、目标方位解算与导航点设定1、相机成像原理2、Python实现目标定位 总结 前言 Darknet_ros是一个基于ROS(机器人操作系统)的开源深度学习框架,它使用YOLO算法进行目标检测和识别。YOLO算…

Apache Storm入门介绍之三分钟看懂Apache Storm

文章目录 0.前言1. 什么是 Apache Storm?1.1. Nimbus1.2. Zookeeper1.3. Supervisor1.4. Worker1.5 集群模式下各组件职责 2. 核心概念2.1基本架构和任务模型2.2 工作流程 3. 源码地址3.1. 代码结构3.1. 核心模块介绍 4. Storm入门实例0.创建java工程并引入依赖1. 创…

印度转向第一人口大国的背后,是红利还是负担?

KlipC报道:印度正在成为全球第一人口大国,人们对于该事件的关注也持续不断。 KlipC的合伙人Andi Duan表示:“自1881年以来,印度人口就一直增长,据联合国人口统计的数据显示”,今年4月印度人口已经成为全球最…

ElasticSearch_学习笔记

一、初始elasticsearch 什么是elasticsearch? 一个开源的分布式搜索引擎,可以用来时限搜素、日志统计、分析、系统监控等功能。什么是elasitc stack(ELK)? 是以elasticsearch为核心的技术栈,包括 beats、L…

C#——多线程之Thread

C#——多线程之Thread 前言一、Thread是什么?二、各应用场景以及实例分析1.前台线程和后台线程:2.异步处理3.线程状态及手动销毁线程4.线程同步/等待线程完成 总结 前言 上次简单讲述了关于多线程中Task的相关应用以及场景。今天我们来看一下多线程中Th…

这就是ChatGPT,走进我们的生活!

这就是ChatGPT,走进我们的生活! 早在年初,合作导师将我叫过去,让我了解学习一下ChatGPT,看能不能对我们的生活有所帮助。一直使用着国内镜像,五月份我才注册了OpenAI的账户。如今,打开购物商城购…

安全测试国家标准解读——并发程序安全

本系列文章主要围绕《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》进行讲解,该标准是2020年4月28日,由国家市场监督管理总局、国家标准化管理委员会发布,2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理&#xff…