Spring事务和事务传播机制(1)

news2024/11/15 16:02:32

前言🍭

❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️

Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客

在Spring框架中,事务管理是一种用于维护数据库操作的一致性和完整性的机制。Spring事务管理提供了灵活的方式来处理事务,包括事务的创建、提交、回滚以及事务的传播行为。

一、为什么需要事务?🍭

事务定义:

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

为什么要用事务?

比如转账分为两个操作:

第一步操作:A 账户 -100 元。

第二步操作:B 账户 +100 元。

如果没有事务,第一步执行成功了,第二步执行失败了,那么 A 账户平白无故的 100 元就“人间蒸 发”了。而如果使用事务就可以解决这个问题,让这⼀组操作要么⼀起成功,要么⼀起失败。

二、Spring 中事务的实现🍭

Spring 中的事务操作分为两类:

  1. 编程式事务(手动写代码操作事务)。
  2. 声明式事务(利用注解自动开启和提交事务)。

在开始讲解它们之前,咱们先来回顾事务在 MySQL 中是如何使用的。

1、MySQL 中的事务使用🍉

事务在 MySQL 有 3 个重要的操作:开启事务、提交事务、回滚事务,它们对应的操作命令如下:

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

2、Spring 编程式事务(了解)🍉

Spring 手动操作事务和上面MySQL 操作事务类似,它也是有 3 个重要操作步骤:

  • 开启事务(获取事务)。
  • 提交事务。
  • 回滚事务。

SpringBoot 内置了两个对象,DataSourceTransactionManager 用来获取事务(开启事务)、提交或回滚事务的,而TransactionDefinition 是事务的属性,在获取事务的时候需要将 TransactionDefinition 传递进去从而获得⼀个事务 TransactionStatus,实现代码如下:

package com.example.demo.controller;

import com.example.demo.entity.UserInfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;

@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;
        }
        // 1.开始事务
        TransactionStatus transactionStatus =
                transactionManager.getTransaction(transactionDefinition);

        // 手动设置创建时间和修改时间的默认值
        userInfo.setCreatetime(LocalDateTime.now().toString());
        userInfo.setUpdatetime(LocalDateTime.now().toString());

        int result = userService.add(userInfo);
        System.out.println("添加:" + result);

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


        return result;
    }
}

因为回滚了事务,所以数据库中不会有wangwu这个用户。

从上述代码可以看出,以上代码虽然可以实现事务,但操作也很繁琐,有没有更简单的实现方法呢?请看下面声明式事务。

3、Spring 声明式事务(自动)🍉

声明式事务的实现很简单,只需要在需要的方法上添加 @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 注解和不设置 @Transactional,观察它们的执行区别:

如果添加了 @Transactional注解就不会添加用户,因为程序报错了,它会自动回滚。如果没有@Transactional注解,就会添加用户,然后给前端报错,这是非常危险的。

Ⅰ、@Transactional 作用范围 🍓

@Transactional 可以用来修饰方法或类:

  • 修饰方法时:需要注意只能应用到 public 方法上,否则不生效。推荐此种用法。
  • 修饰类时:表明该注解对该类中所有的 public 方法都生效。

Ⅱ、@Transactional参数说明🍓

参数作用
value当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器.
transactionManager当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器.
propagation事务的传播行为,默认值为Propagation.REQUIRED
isolation事务的隔离级别.默认值为Isolation.DEFAULT
timeout事务的超时时间,默认值为-1.如果超过该时间限制但事务还没有完成,则自动回滚事务.
readOnly指定事务是否为只读事务,默认值为false;为了忽略那些不需要事务的方法,比如读取数据,
可以设置read-only为true.
rollbackFor用于指定能够触发事务回滚的异常类型,可以指定多个异常类型.
rollbackForClassName用于指定能够触发事务回滚的异常类型,可以指定多个异常类型.
noRollbackFor抛出指定的异常类型,不回滚事务.也可以指定多个异常类型.
noRollbackForClassName抛出指定的异常类型,不回滚事务,也可以指定多个异常类型.

Ⅲ、注意事项🍓

@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);
        try {
            int num=10/0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return result;
    }

 数据库中也有了wangwu:

事务并没有进行回滚。

事务不会自动回滚解决方案🍓

①解决方案1🍒

对于捕获的异常,事务是会自动回滚的,因此解决方案1就是可以将异常重新抛出,具体实现如下:

@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) {
            System.out.println(e.getMessage());
            throw e;
        }
        return result;
    }

②解决方案2🍒

手动回滚事务,在方法中使用TransactionAspectSupport.currentTransactionStatus() 可 以得到当前的事务,然后设置回滚方法 setRollbackOnly 就可以实现回滚了,具体实现代码如下:

@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) {
            System.out.println(e.getMessage());
            /*throw e;*/
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }

Ⅳ、@Transactional 工作原理🍓

@Transactional 是基于 AOP 实现的,AOP又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用JDK 的动态代理,如果目标对象没有实现了接口,会使用CGLIB 动态代理。

@Transactional 在开始执行业务之前,通过代理先开启事务,在执行成功之后再提交事务。如果中途遇到的异常,则回滚事务。

@Transactional 实现思路预览:

@Transactional 具体执行细节如下图所

Spring事务、事务隔离级别、事务传播机制(spring事务的实现方式和原理以及隔离级别?) | 半码博客

三、事务隔离级别🍭

1、事务特性🍉

事务有4 ⼤特性(ACID),原子性、持久性、⼀致性和隔离性,具体概念如下:

  • 原子性:⼀个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过⼀样。
  • ⼀致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
  • 隔离性:数据库允许多个并发事务同时对其数据进⾏读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不⼀致。事务隔离分为不同级别,包括读未提交 (Read uncommitted)、读提交 (read committed)、可重复读 (repeatable read) 和串行化 (Serializable)。
上⾯ 4 个属性,可以简称为ACID。
原⼦性(Atomicity,或称不可分割性)
⼀致性(Consistency)
隔离性(Isolation,⼜称独立性)
持久性(Durability)。

而这 4 种特性中,只有隔离性(隔离级别)是可以设置的。

为什么要设置事务的隔离级别?
设置事务的隔离级别是用来保障多个并发事务执行更可控,更符合操作者预期的。
什么是可控呢?
比如近几年比较严重的新冠病毒,我们会把直接接触到确证病例的人员隔离到酒店,而把间接接触者(和直接接触着但未确诊的人)隔离在自己的家中,也就是针对不同的人群,采取不同的隔离级别,这种隔离方式就和事务的隔离级别类似,都是采取某种行动让某个事件变的“更可控”。而事务的隔离级别就是为了防止,其他的事务影响当前事务执行的一种策略。

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

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

相关文章

HLK-LD105/2410B/2420模块测试

HLK105/2410B/2420模块测试 📌模块资料地址:https://h.hlktech.com/Mobile/download 🌿HLK-LD105模块: 10G微波雷达 🌿HLK-LD2420-24G:24G毫米波雷达 🌿HLK-LD2410B-24G:24…

网络安全--wazuh环境配置及漏洞复现

目录 一、wazuh配置 二、wazuh案例复现 一、wazuh配置 1.1进入官网下载OVA启动软件 Virtual Machine (OVA) - Installation alternatives (wazuh.com) 1.2点击启动部署,傻瓜式操作 1.3通过账号:wazuh-user,密码:wazuh进入wazuh…

【NOIP】XR-4模拟赛,Oler教练的上班策略

author:&Carlton tag:模拟 topic:【NOIP】XR-4模拟赛,Oler教练的上班策略 language:C website:洛谷 date:2023年8月19日 目录 题目 我的题解 思路 源代码 改进 题目 我的题解 思路…

iptables防火墙(SNAT与DNAT)

目录 1 SNAT 1.1 SNAT原理与应用 1.2 SNAT工作原理 1.3 SNAT转换前提条件 2 SNAT示例 ​编辑 2.1 网关服务器配置 2.1.1 网关服务器配置网卡 2.1.2 开启SNAT命令 2.2 内网服务器端配置 2.3 外网服务器端配置 2.4 网卡服务器端添加规则 2.5 SNAT 测试 3 DNAT 3.1 网卡…

Windows 11 下使用 VMWare Workstation 17 Pro 新建 CentOS Stream 9 64位 虚拟机 并配置网络

文章目录 为什么选择 CentOS Stream 9下载安装访问连接快照克隆网络配置 为什么选择 CentOS Stream 9 CentOS Linux 8: 已经过了 End-of-life (EOL)CentOS Linux 7: EOL Jun 30th, 2024CentOS Stream 8: EOL May 31st, 2024CentOS Stream 9: End of RHEL9 full support phase …

DTC 19服务学习1

在UDS(统一诊断服务)协议中,0x19是用于DTC(诊断故障代码)信息的服务。以下是你提到的子服务的功能和作用: 0x01 - 报告DTC按状态掩码。这个子服务用于获取当前存储在ECU中的DTC列表。状态掩码用于过滤DTC&a…

redis闪退的三大解决办法(windows版本)

目录 一、遇到问题 二、出现问题的原因 三、三大启动方法 (一)启动服务端的命令一 (二)启动服务端命令二 (三)必解决redis服务端 一、遇到问题 下载完成redis的5的版本,要进行启动redis的…

UML基础模型

目录 1.抽象类2.接口3.继承4.实现接口5.关联关系6.聚合关系7.合成(组合)关系8.依赖关系 1.抽象类 矩形框代表一个类(Class)。 类图分为三层: 第一层显示类的名称,如果是抽象类,就用斜体显示&am…

kafka--kafka基础概念-ISR详解

kafka基础概念-ISR详解 主要是讲 主 往 从同步中的问题 当绿色P1接收到写入的数据,要同步到紫色的P1S1和P1S2 如何保证一致性呢? 使用In Sync Replicas 也就是ISR概念 为什么不一致的? 因为P1S1同步数据 可能花费 50ms P1S2可能花费60ms…

G0第26章:微服务概述与gRPCprotocol buffers

Go微服务与云原生 1、微服务架构介绍 单体架构(电商) SOA架构(电商) 微服务架构(电商) 优势 挑战 拆分 发展史 第一代:基于RPC的传统服务架构 第二代:Service Mesh(istio) 微服务架构分层 核心组件 Summar…

云安全与多云环境管理:讨论在云计算和多云环境下如何保护数据、应用程序和基础设施的安全

随着云计算和多云环境的广泛应用,企业正面临着数据、应用程序和基础设施安全的新挑战。在这个数字化时代,保护敏感信息和业务运作的连续性变得尤为重要。本文将深入探讨在云计算和多云环境下如何有效地保护数据、应用程序和基础设施的安全。 章节一&…

【Teamcity 安装及入门使用】

Teamcity 安装及入门使用 前言安装无Mysql版本有Mysql版本 启动创建超管用户账户和密码忘记密码结尾语 前言 前不久,teamcity更新了2023.05.2版本,我对teamcity也有一段时间的学习了,所以想写一篇博客来记录一下这段时间的学习过程。 teamc…

这是我的纪念日

我的1460天 写这篇文章,是为了纪念自己这一千多个日日夜夜,我的热爱总算有了回报。 每次看到有小伙伴点赞,评论的时候,我都很开心,我知道自己的选择是正确的,我喜欢分享自己的所见所学,我也很…

7-3 数字加密

分数 15 全屏浏览题目 切换布局 作者 陈建海 单位 浙江大学 输入一个四位数,将其加密后输出。方法是将该数每一位上的数字加9,然后除以10取余,做为该位上的新数字,最后将千位和十位上的数字互换,百位和个位上的数字…

vue-element-admin新增view后点击侧边栏加载慢问题

按照官网文档新增view 新增之后点击显示一直在加载中 解决方案:删除script中这段代码

【自创】关于前端js的“嵌套地狱”的遍历算法

欢迎大家关注我的CSDN账号 欢迎大家关注我的哔哩哔哩账号:卢淼儿的个人空间-卢淼儿个人主页-哔哩哔哩视频 此saas系统我会在9月2号之前,在csdn及哔哩哔哩上发布成套系列教学视频。敬请期待!!! 首先看图 这是我们要解…

<数据结构与算法>二叉树堆的实现

目录 前言 一、树的概念及结构 1 树的概念 2 树的相关概念 二、二叉树的概念及结构 1.二叉树的概念 2. 特殊的二叉树 3. 二叉树的性质 4.二叉树的存储结构 三、二叉树的顺序结构及实现 1.堆的性质 2.堆的插入 3.堆的实现 堆的结构体 HeapInit 初始化 HeapPush 插入 HeapPop 删…

攻防世界-warmup

原题解题思路 只有一张图片,就查看源代码,有一个source.php。 查看source.php,白名单中还有一个hint.php。 hint.php告诉我们flag的位置ffffllllaaaagggg 但是直接跳转是没用的,构造payload。 http://61.147.171.105:55725/sourc…

Android12之com.android.media.swcodec无法生成apex问题(一百六十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

excel中有哪些通配符、excel配置问题,数学函数篇1之sum系列

学习excel前需要明确的是事:   在学习excel函数之前,大家需要明确一件事,excel现在设计到了一些新函数,这些新函数只能存在于office365、office2019及更 新版本之中,所以建议大家在学习时安装较新的版本,…