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

目录

需要知道:

🍑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 是加入到当前事务中,并没有创建事务的保存点,因此出现了回滚就是整个事务回滚,这就是嵌套事务和加入事务的区别。


 和七月就要说再见啦~🥰

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端学习——Vue (Day8)

Vue3 create-vue搭建Vue3项目 注意要使用nodejs16.0版本以上,windows升级node可以西安使用where node查看本地node位置,然后到官网下载msi文件,在本地路径下安装即可 安装完可以使用node -v检查版本信息 项目目录和关键文件 组合式API - s…

ALLEGRO之Tools

本文主要介绍了ALLEGRO的Tools菜单。 (1)Create Module:暂不清楚; (2)Padstack:主要用于查看焊盘尺寸; (3)Pad:暂不清楚; &#xff…

Segment anything(图片分割大模型)

目录 1.Segment anything 2.补充图像分割和目标检测的区别 1.Segment anything 定义:图像分割通用大模型 延深:可以预计视觉检测大模型,也快了。 进一步理解:传统图像分割对于下图处理时,识别房子的是识别房子的模型…

app自动化测试之Appium问题分析及定位

使用 Appium 进行测试时,会产生大量日志,一旦运行过程中遇到报错,可以通过 Appium 服务端的日志以及客户端的日志分析排查问题。 Appium Server日志-开启服务 通过命令行的方式启动 Appium Server,下面来分析一下启动日志&#…

飞桨AI Studio可以玩多模态了?MiniGPT4实战演练!

MiniGPT4是基于GPT3的改进版本,它的参数量比GPT3少了一个数量级,但是在多项自然语言处理任务上的表现却不逊于GPT3。项目作者以MiniGPT4-7B作为实战演练项目。 创作者:衍哲 体验链接: https://aistudio.baidu.com/aistudio/proj…

Vue 基础语法(二)

一、背景: 我们对于基础语法,说白了就是实现元素赋值,循环,判断,以及事件响应即可! 二、v-bind 我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 V…

IO流简述

IO流IO流使用场景 什么是IO流常用的IO流字节流字符流缓冲流 BIO、NIO、AIO的区别 IO流 IO流使用场景 如果操作的是纯文本文件,优先使用字符流如果操作的是图片、视频、音频等二进制文件。优先使用字节流如果不确定文件类型,优先使用字节流。字节流是万能…

Java版知识付费 Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台免费搭建

提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含:录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署,免费售后,专业技术指导,支持PC、APP、H5、小程序多终端同步,支持二次开发…

springboot整合tio-websocket方案实现简易聊天

写在最前: 常用的http协议是无状态的,且不能主动响应到客户端。最初想实现状态动态跟踪只能用轮询或者其他效率低下的方式,所以引入了websocket协议,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务…

StopWatch与ThreadLocal

目录 1、StopWatch 1、1作用: 1、2方法: 1、3使用方法 2、ThreadLocal 2、1什么是ThreadLocal 2、2简单例子 2、3使用ThreadLocal带来的四个好处 2、4主要方法 2、5ThreadLocal内存泄漏问题 1、StopWatch 1、1作用: 统计代码块耗时时…

vue中使用axios发送请求时,后端同一个session获取不到值

问题描述: 在登录页面加载完成后通过axios请求后端验证码接口(这时后端会生成一个session用于保存验证码数值),当输入完用户名、密码、验证码后请求登录接口,报错验证码输入错误,打印后端保存验证码的sessi…

【ArcGIS Pro二次开发】(54):三调名称转用地用海名称

三调地类和用地用海地类之间有点相似但并不一致。 在做规划时,拿到的三调,都需要将三调地类转换为用地用海地类,然后才能做后续的工作。 一般情况下,三调转用地用海存在【一对一,多对一和一对多】3种情况。 前2种情况…

11-3_Qt 5.9 C++开发指南_QSqlQuery的使用(QSqlQuery 是能执行任意 SQL 语句的类)

文章目录 1. QSqlQuery基本用法2. QSqlQueryModel和QSqlQuery联合使用2.1 可视化UI设计框架2.1.1主窗口的可视化UI设计框架2.1.2 对话框的可视化UI设计框架 2.2 数据表显示2.3 编辑记录对话框2.4 编辑记录2.5 插入记录2.6 删除记录2.7 记录遍历2.8 程序框架及源码2.8.1 程序整体…

【RabbitMQ】Linux系统服务器安装RabbitMQ

一、下载 首先应该下载erlang,rabbitmq运行需要有erland环境。 官网地址:https://www.erlang.org/downloads 下载rabbitmq 官网环境:https://www.rabbitmq.com/download.html 注意:el7对应centos7,el8对应centos8…

探索运营商渠道佣金数字化运营

当前全球经济增长放缓,行业竞争持续加剧已是常态,用户需求越发苛刻、经营成本不断上升。内忧外患,企业经营如何突围?越来越多的企业发现,融合数字化技术的IT解决方案为企业提供了一种解决问题的可能。 数字化运营可以帮…

B. Binary Cafe(二进制的妙用)

题目:Problem - B - Codeforces 总结: 对于该题最简单的方法为使用二进制的数表示状态 例如: 对于一个数7的二进制:111 它的每一位都可表示两种状态我们可以理解为取或者不取 对于7这个数字它可以表示一种状态即在三个位置都…

道本科技||全面建立国有企业合规管理体系

为全面深化国有企业法治建设,不断加强合规管理,防控合规风险,保障企业稳健发展,近日,市国资委印发《常州市市属国有企业合规管理办法(试行)》(以下简称《办法》)&#xf…

小研究 - JVM GC 对 IMS HSS 延迟分析(二)

用户归属服务器(IMS HSS)是下一代通信网(NGN)核心网络 IP 多媒体子系统(IMS)中的主要用户数据库。IMS HSS 中存储用户的配置文件,可执行用户的身份验证和授权,并提供对呼叫控制服务器…

【Matlab】判断点和多面体位置关系的两种方法实现

我的主页: 技术邻:小铭的ABAQUS学习的技术邻主页博客园 : HF_SO4的主页哔哩哔哩:小铭的ABAQUS学习的个人空间csdn:qgm1702 博客园文章链接: https://www.cnblogs.com/aksoam/p/17590039.html 分别是向量判别法&…

Azure pipeline自动化打包发布

pipeline自动化,提交代码后,就自动打包,打包成功后自动发布 第一步 pipeline提交代码后,自动打包。 1 在Repos,分支里选择要触发的分支,这里选择cn_china,对该分支设置分支策略 2 在生产验证中增加新的策略 3 在分支安…