Spring事务及传播机制

news2024/11/15 23:22:50

概念

在MySQL中介绍过,当同一时间出现一起读写数据的情况,可能会导致最终的结果出错,因此可以使用事务来提高隔离级别
而Spring中也可以实现事务

手动添加事务

使用SpringBoot中的DataSourceTransactionManager对象可以获取事务,提交事务,回滚事务

TransactionDefinition是事务的属性,在获取事务时需要传入这个参数

而TransactionStatus则是在获取事务时获取的对象,最终回滚时使用

@RestController
@RequestMapping("url")
public class 实现类 {
    @Autowired
    private DataSourceTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("url")
    public 相关方法() {

        //开启事务
        TransactionStatus transactionStatus =
                transactionManager.getTransaction(transactionDefinition);
        //处理事务

        //回滚事务
        transactionManager.rollback(transactionStatus);
    }

例如:

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private DataSourceTransactionManager transactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/add")
    public int add(UserInfo userInfo) {
        if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
                !StringUtils.hasLength(userInfo.getPassword())) {
            return 0;
        }

        //开启事务
        TransactionStatus transactionStatus =
                transactionManager.getTransaction(transactionDefinition);
        int result = userService.add(userInfo);

        //回滚事务
        transactionManager.rollback(transactionStatus);

        return result;
    }
}

在页面中,传输了参数username = 1, password = 1
但是在数据库中,并没有出现这行数据
在这里插入图片描述

自动添加事务

使用@Transactional注解可以快速添加事务

@Transactional
@RequestMapping("/insert")
public Integer insert(UserInfo userInfo) {
    if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
            !StringUtils.hasLength(userInfo.getPassword())) {
        return 0;
    }
    int result = userService.add(userInfo);
    }
    return result;
}

如果没有异常,那么会自动提交事务,如果有异常,事务会进行回滚

例如:在类中添加空指针异常
如果没有添加@Transactional那么在异常出现前数据已经上传到数据库

@RequestMapping("/insert")
public Integer insert(UserInfo userInfo) {
    if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
            !StringUtils.hasLength(userInfo.getPassword())) {
        return 0;
    }
    int result = userService.add(userInfo);
	int num = 1 / 0;
    return result;
}

在这里插入图片描述
在这里插入图片描述
而加了@Transactional注解,就可以自动回滚事务,数据库中就没有这行数据了
在这里插入图片描述
在这里插入图片描述
而如果我们添加了try,catch语句,spring就不会感知到异常的存在了,也就不会进行事务的回滚了

@Transactional //声明式事务(没有错误自动提交)
@RequestMapping("/insert")
public Integer insert(UserInfo userInfo) {
    if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
            !StringUtils.hasLength(userInfo.getPassword())) {
        return 0;
    }
    int result = userService.add(userInfo);
    try{
        int num = 1 / 0;
    } catch (Exception e){
        e.printStackTrace()
    }

    return result;
}

在这里插入图片描述
在这里插入图片描述
如果我们还想要事务进行自动回滚,那么可以使用throw将异常抛出,这样spring就能再次感知到异常的存在了

@Transactional //声明式事务(没有错误自动提交)
@RequestMapping("/insert")
public Integer insert(UserInfo userInfo) {
    if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
            !StringUtils.hasLength(userInfo.getPassword())) {
        return 0;
    }
    int result = userService.add(userInfo);
    try{
        int num = 10 / 0;
    } catch (Exception e){
        e.printStackTrace();
            throw e;
    }
    return result;
}

在这里插入图片描述
在这里插入图片描述

如果不想要页面出现报错信息,那么可以不添加throw语句,而是手动回滚事务

@Transactional //声明式事务(没有错误自动提交)
@RequestMapping("/insert")
public Integer insert(UserInfo userInfo) {
    if (userInfo == null || !StringUtils.hasLength(userInfo.getUsername()) ||
            !StringUtils.hasLength(userInfo.getPassword())) {
        return 0;
    }
    int result = userService.add(userInfo);
    try{
        int num = 10 / 0;
    } catch (Exception e){
        e.printStackTrace();
      	TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
    }

    return result;
}

在这里插入图片描述
在这里插入图片描述

事务隔离级别设置

当不同事务同时对数据库进行数据操作,就会出现问题,因此可以针对不同的情景设置不同的隔离级别
在这里插入图片描述

在@Transactional注解中可以设置事务的隔离级别
在这里插入图片描述

代码含义问题
Isolation.DEFAULT默认级别 以数据库隔离级别执行
Isolation.READ_UNCOMMITTED读未提交 可以读未提交数据存在脏读问题
Isolation.READ_COMMITED读已提交 只能读到已经提交事务存在不可重复读问题
Isolation.REPEATABLE_READ可重复读存在幻读问题
Isolation.SERIALIZABLE串行化性能低

事务传播机制

在项目中会存在多个方法链式调用,而每一个方法都有可能存在事务,因此存在不同的事物传播机制
在这里插入图片描述
分别有如下几种事物传播级别:

代码说明
Propagation.REQUIRED(默认)如果当前存在事务则加入事务,都则创建一个事务
Propagation.SUPPORTS如果当前存在事务就加入事务,否则就以非事务方式运行
Propagation.MANDATORY如果当前存在事务就加入事务,否则抛出异常
Propagation.REQUIRES_NEW不管当前有没有事务,都创建并使用新事务
Propagation.NOT_SUPPORTED不管当前有没有事务,都以非事务方式运行
Propagation.NEVER以非事务形式运行,如果当前存在事务就抛出异常
Propagation.NESTED如果当前存在事务,则创建一个事务作为当前事务的嵌套事务运行,当作REQUIRED

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

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

相关文章

计算机科学导论笔记(六)

目录 八、算法 8.1 概念 8.1.1 非正式定义 8.1.2 示例 8.1.3 定义动作 8.1.4 细化 8.1.5 泛化 8.2 三种结构 8.2.1 顺序 8.2.2 判断 8.2.3 循环 8.3 算法的表示 8.3.1 UML 8.3.2 伪代码 8.4 更正式的定义 8.5 基本算法 8.5.1 求和 8.5.2 求积 8.5.3 最大和最…

Egg:使用joi进行参数校验以及注册接口小demo

目录 前言: 准备工作: 前端代码: 后端目录截图: 1.获取参数 2.校验参数 3.查询数据库中是否已经存在该用户 4.用户入库 5.测试一哈 添加用户成功 同样的用户名再注册一遍 ​编辑总结: 前言: 在阅…

C#基础之基础语法(一)

总目录 文章目录总目录前言一、C#简述1 C#是什么?2 .Net平台3. C# 和.Net的关系4. 集成开发环境(IDE)二、控制台应用程序1. 常用代码2.注意事项三、基础语法1.编写C#代码注意事项2.C#注释2. 变量&标识符&关键字4. 变量,字…

unity 面试汇总

1、什么是协同程序?答:在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句话说,开启协程就是开启一个可以与程序并行的逻辑。可以用来控制运动、序列以及对象的行为。2、Unity3D中的碰撞器和触发器的区别&#xff…

【C++进阶】四、AVL树(二)

目录 前言 一、AVL树的概念 二、AVL树节点的定义 三、AVL树的插入 四、AVL树的旋转 4.1 左单旋 4.2 右单旋 4.3 左右双旋 4.4 右左双旋 五、AVL树的验证 六、AVL树的性能 七、完整代码 前言 前面对 map/multimap/set/multiset 进行了简单的介绍,在其文…

2023年湖北武汉安全员C证报考条件是什么?考试题型是什么 启程别

2023年湖北武汉安全员C证报考条件是什么?考试题型是什么 启程别 武汉安全员C证报考条件: 1.注册地在本市的施工单位在职“三类人员”可申请参加安全生产考核; 2、职业道德良好,身体健康,年龄不超过60周岁&#xff08…

pdf多页合并为一页方法总结,你觉得哪个最好?

PDF格式的文件在现代办公中是不可或缺的,许多人在工作中需要频繁处理PDF文档。然而,当我们需要阅读多个PDF文件时,不断切换不同的文件并一个一个地打开查阅会非常麻烦。为了提高阅读效率,人们一般会将pdf多页合并为一页。那么&…

传输线的物理基础(四):传输线的驱动和返回路径

驱动一条传输线对于将信号发射到传输线的高速驱动器,传输线在传输时间内的输入阻抗将表现得像一个电阻,相当于线路的特性阻抗。鉴于此等效电路模型,我们可以构建驱动器和传输线的电路,并计算发射到传输线中的电压。等效电路如下图…

虹科分享 | 网络流量监控 | 数据包丢失101

什么是数据包? 数据包是二进制数据的基本单位,在网络连接的设备之间编号和传输,无论是在本地还是通过互联网。一旦数据包到达其目的地,它就会与其他数据包一起按编号重新组合,回到最初传输的较大消息中。 数据包是我们…

2022(二等奖)C2594江淮分水岭植被碳汇时空可视化系统

作品介绍 一、需求分析 1.1 设计背景 气候变化是全球性问题,随着二氧化碳排放的增加生物的生存与生命受到威胁。人类活动对自然界生态系统的破坏,不仅降低了地球生物圈的生产力,威胁到人类社会未来经济的发展,同时还破坏了陆地与…

WireShark如何抓包,各种协议(HTTP、ARP、ICMP)的过滤或分析,用WireShark实现TCP三次握手和四次挥手

WireShark一、开启WireShark的大门二、如何抓包 搜索关键字2.1 协议过滤2.2 IP过滤2.3 过滤端口2.4 过滤MAC地址2.5 过滤包长度2.6 HTTP模式过滤三、ARP协议分析四、WireShark之ICMP协议五、TCP三次握手与四次挥手5.1 TCP三次握手实验5.2 可视化看TCP三次握手5.3 TCP四次挥手5.…

【大数据处理与可视化】一 、大数据分析环境搭建(安装 Anaconda 3 开发环境)

【大数据处理与可视化】一 、大数据分析环境搭建(安装 Anaconda 3 开发环境)实验目的实验内容实验步骤一、下载Anaconda安装包二、安装Anaconda3三、验证Anaconda是否安装成功四、Jupyter Notebook的使用1. 启动Anaconda自带的Jupyter Notebook2. 在code…

Volatile关键字

Volatile关键字和JMM内存模型一JUC并发包API 包介绍二JMM(Java Memory Model)三 volatile关键字3.1.可⻅性3.1.1.问题演示3.1.1.1案例代码3.1.1.2.案例分析3.1.2.volatile 保证可见性演示3.1.2.1对number添加了volatile修饰3.1.2.2运⾏结果是&#xff1a…

Docker学习(二十一)构建 java 项目基础镜像

目录1.下载 JDK 包2.编写 Dockerfile3.构建镜像4.创建容器测试1.下载 JDK 包 JDK各版本官网下载地址: https://www.oracle.com/java/technologies/downloads/archive/#JavaSE 这里我们以 JDK 8u351 为例,点击 Java SE (8U211 and later)。 点击下载 jd…

Mysql问题:[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause

1 问题描述 使用Navicat连接到MySQL(版本:8.0.18),执行查询: select * from t_user WHERE user_name admin查询结果没有问题,但是报错: [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY claus…

分布式 微服务

微服务学习 soa和微服务 业务系统实施服务化改造之后,原本共享的业务被拆分形成可复用的服务,可以在最大程度上避免共享业务的重复建设、资源连接瓶颈等问题。那么被拆分出来的服务是否也需要以业务功能为维度来进行拆分和独立部署,以降低业…

学习streamlit-4

st.slider 今天学习st.slider滑块组件的使用。 st.slider滑块组件通常被用来作为应用的输入,支持整数、浮点数、日期、时间和日期时间。 下面的示例程序包含以下简单功能,以演示st.slider滑块组件: 用户通过调整滑块选择值应用打印出所选…

C++面向对象编程之五:友元(friend)

C中,允许一个类的非共有成员被这个类授予友元(friend)关系的全局函数,另一个类,或另一个类中的成员函数访问。友元不是一个类中的成员,所以它们不受声明出现部分的访问权限(public,p…

Binder通信原理与弊端解析

Binder 定义 简单来说,Binder 就是用来Client 端和 Server 端通信的。并且 Client 端和 Server 端 可以在一个进程也可以不在同一个进程,Client 可以向 Server 端发起远程调用,也可以向Server传输数据(当作函数参数来传&#xff…

USART_GetITStatus与 USART_GetFlagStatus的区别

文章目录共同点不同点USART_GetITStatus函数详解USART_GetFlagStatus函数共同点 都能访问串口的SR寄存器 不同点 USART_GetFlagStatus(USART_TypeDef USARTx, uint16_t USART_FLAG):* 该函数只判断标志位(访问串口的SR寄存器)。在没有使能…