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

目录

事务

回顾: 什么是事务

为什么需要事务

事务的操作

Spring事务的实现

Spring编程式事务(简单了解即可, 问就是基本不用)

 观察事务提交

观察事务回滚

Spring声明式事务 @Transactional

@Transactional作用


事务

回顾: 什么是事务

定义: 事务是指逻辑上的一组操作, 构成这组操作的各个单元, 要么全部执行, 要么全部不执行.

为什么需要事务

一般在进行程序设计中, 我们一般都会用到事务.

比如当家人给我们转账(2000元)时, 共有两个操作: 家人扣款2000, 我们的账户增加2000元.

但在家人扣款之后, 出现了一个问题: 此时一位自信的挖掘机操作员把光缆给"不小心"挖断了.

然后这就导致我们账户增加余额的操作得不到落实 .

因此这里引入事务: 使得家人扣款和我们账户到账是同一个事务, 这时如果中间执行这个事务时,就会发生异常, 然后就会回滚, 恢复数据: 家人账户+2000.

事务的操作

事务的操作主要有三步:

1.开启事务start transaction(在一组操作之前开启事务).

2.提交事务: commit.(这组操作全部执行成功, 就会全部落实)

3.回滚: rollback(这中间任意一个操作出现异常, 就会回滚事务, 即恢复初始状态)  

Spring事务的实现

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

1.编程式事务(手动写代码操作事务)

2.声明式事务(利用注解操作事务)

我们通过一个简单的小项目来说明这个事务:

Spring编程式事务(简单了解即可, 问就是基本不用)

Spring手动操作事务和之前mysql操作事务类似.,有三个重要的操作步骤:

开启事务(获取事务)

提交事务

回滚事务 

SpringBoot内置了两个对象:

1. DataSourceTransactionManager 事务管理器. 用来获取事务(开启事务), 提交或回滚事务.

2.TransactionDefinition是事务的属性, 在获取事务时需要将TransactionDefinition传递进去获取一个TransactionStatus.

还是通过代码练习(就以一个简单的注册提交为示例, 很简单, 自行编写即可(作者懒得粘)):

@RestController
@RequestMapping("/user")
public class UserController {
    //JDBC事务管理器
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;
    //定义事务属性
    @Autowired
    private TransactionDefinition transactionDefinition;
    @Autowired
    private UserService userService;

    @RequestMapping("/registry")
    public String registry(String name, String password) {
        //开启事务
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        //用户这侧
        userService.registryUser(name, password);
        //提交事务
        dataSourceTransactionManager.commit(transactionStatus);
        //回滚事务
        //dataSourceTransactionManager.rollback(transactionStatus);
        return "注册成功";
    }
}

 观察事务提交

运行程序: http://127.0.0.1:8080/user/registry?name=admin&password=admin

观察数据库的结果, 数据插入成功.

观察事务回滚

运行程序:

 

虽然这里显示"注册成功", 但是数据库中并没有新增数据.

 

以上通过编程方法确实能够实现事务, 但是有没有什么更简单的方法呢?

Spring声明式事务 @Transactional

声明式事务很简单, 只需要在事务的方法上添加@Transactional注解就可以实现了. 无需手动开启事务和提交事务, 进入方法时自动开启事务, 方法执行完会自动提交事务, 如果中途发生了没有处理的异常会自动回滚事务.

我们来看代码实现:

@RestController
@RequestMapping("/user")
public class UserController1 {
    @Autowired
    private UserService1 userService;

    @Transactional
    @RequestMapping("/registry")
    public String registry(String name, String password) {
        //用户注册
        userService.registryUser(name, password);
        return "注册成功";
    }
}

运行程序, 发现数据插入成功(通过这个id情况我们也可以知道之前那个事务中的内容确实是执行了, 但是回滚了):

 

修改程序, 使之出现异常:

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController1 {
    @Autowired
    private UserService1 userService;

    @Transactional
    @RequestMapping("/registry")
    public String registry(String name, String password) {
        //用户注册
        userService.registryUser(name, password);
        log.info("用户数据插入成功");
        //强制程序发生异常
        int a = 10 / 0;
        return "注册成功";
    }
}

观察:

 

观察后端: 虽然日志显示数据插入成功, 但是数据库却没有新增数据, 这证明了事务进行了回滚. 

@Transactional作用

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

修饰方法(推荐)时: 只有修饰public方法时才生效(修饰其它方法时不报错, 也不生效).

修饰类时: 对@Transactional修饰类中所有的public方法都生效.

方法/类被@Transactional修饰时, 在目标方法执行开始之前, 会自动开启事务, 方法执行结束之后, 自动提交事务(即程序运行成功时, 自动提交).

那么在程序出现异常时什么时候会进行事务回滚, 什么时候不进行事务回滚呢? 这就比较复杂了.

让我们通过一张图看一下:

我们对之前的代码进行异常捕获再试一下:

我们发现: 虽然程序出错了, 但是由于异常被捕获了, 所以事务依然得到了提交. 

1.重新抛出异常以进行事务回滚:

//对异常进行捕获
try {
    //强制程序发生异常
    int a = 10 / 0;
} catch (Exception e) {
    //再次抛出异常
    throw e;
}

 2.手动回滚事务

//对异常进行捕获
try {
    //强制程序发生异常
    int a = 10 / 0;
} catch (Exception e) {
    //手动进行回滚
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}

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

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

相关文章

最大数字——蓝桥杯十三届2022国赛大学B组真题

问题分析 这道题属于贪心加回溯。所有操作如果能使得高位的数字变大必定优先用在高位,因为对高位的影响永远大于对低位的影响。然后我们再来分析一下,如何使用这两种操作?对于加操作,如果能使这一位的数字加到9则变成9&#xff0…

^_^填坑备忘^_^C#自动化编程实现STK+Exata对卫星互联网星座进行网络仿真

C#实际选择 STK11版本 or STK12版本的问题备注。 【C#自动化客户端调用STK时,实际选择 STK11版本 or STK12版本 的调试运行备注】 以下代码“更新并重新打包备份为”〔testSTKQualNetInterface备份08.1_★避坑★【种子卫星:天线直接安装在卫星上&#…

电机控制系列模块解析(19)—— 反电势观测器

随着现代工业自动化技术的飞速发展,交流电机作为关键的动力装置,其控制精度与效率日益受到重视。其中,无位置传感器控制技术由于其成本低、可靠性高、系统简洁等优点,逐渐成为研究热点。本文将对交流电机反电势观测器这一关键技术…

三维空间刚体运动

三维空间刚体运动是指刚体在三维空间中的运动,这种运动由平移和旋转构成。平移是指物体在空间中沿某一方向移动一定的距离,而旋转则是指物体绕某一轴旋转一定的角度。这两种运动都不会改变物体的形状和大小,因此被称为刚体运动。 在描述三维…

Qt跨平台开发demo(适用萌新)

最近需要参与一款Qt跨平台的软件开发,在此之前,特把基础信息做学习和梳理,仅供参考。 所使用的技术和版本情况如下: 虚拟机:VMware 16.2.5操作系统:ubuntu-20.04.6-desktop-amd64:Mysql数据库…

大模型入坑记:搭建本地大模型微调环境

为了让大模型发挥更大用途,决定在本地搭建大模型微调环境,在原有的PC上加装Tesla V100,前前后后耗时一个多月,遇到若干技术问题,好在目前已基本得到解决,也打破了很多网上店家包括身边专家对GPU搭建上的一些…

正版软件 | Total Uninstall - Windows 全功能卸载程序 新手入门教程

『软件简介』 Total Uninstall 是一款先进的系统监控与卸载工具,它通过创建安装前后的系统快照,为用户提供了一种全新的程序管理方式。这款软件具备两个主要功能:一是能够独立于系统自带的卸载程序,彻底移除已安装的应用程序&…

FPGA -手写异步FIFO

一,FIFO原理 FIFO(First In First Out)是一种先进先出的数据缓存器,没有外部读写地址线,使用起来非常简单,只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成&a…

开源数据可视化大屏对接表单数据实践!

如果你需要一个表单系统,进行数据收集;可以使用tduck填鸭进行私有化部署,进行表单制作,完成数据收集。 在实际业务中,往往需要将收集的数据进行展示或分析;此时就可以使用表单数据推送到TReport中&#xf…

AMBA总线介绍

AMBA(Advanced Microcontroller Bus Architecture)是由ARM(Advanced RISC Machines)公司设计的一种高性能、高带宽的总线架构。AMBA总线广泛应用于各种嵌入式系统中,包括数字信号处理器、图形处理器、嵌入式处理器以及…

收银系统源码--什么是千呼智慧新零售系统?

千呼智慧新零售系统是一套针对零售行业线上线下一体化收银系统。给门店提供线下称重收银、o2o线上商城、erp进销存、精细化会员管理、丰富营销插件等一体化解决方案。多端数据打通,实现线上线下一体化,提升门店工作效率,实现数字化升级&#…

vue3 依赖-组件tablepage-vue3版本1.0.3更新内容

github求⭐ 可通过github 地址和npm 地址查看全部内容 vue3 依赖-组件tablepage-vue3说明文档,列表页快速开发,使用思路及范例-汇总 vue3 依赖-组件tablepage-vue3说明文档,列表页快速开发,使用思路及范例(Ⅰ&#…

【第38天】SQL进阶-SQL设计优化-范式设计(SQL 小虚竹)

回城传送–》《100天精通MYSQL从入门到就业》 文章目录 零、前言一、练习题目二、SQL思路初始化数据什么是范式设计第一范式(1NF)第二范式(2NF)第三范式(3NF) 三、总结四、参考 零、前言 今天是学习 SQL …

期权和期货有什么区别?

今天期权懂带你了解期权和期货有什么区别?期权和期货是两种常见的衍生金融工具,它们在结构和盈利方式上存在一些关键的区别: 期权 期权是一种给予持有者在未来某个时间以特定价格买入或卖出基础资产的权利,但不是义务。期权的主要…

ORACLE 19C RAC DIAG进程消耗大量内存的分析

近期一个ORACLE 19C的RAC环境,多次出现数据库实例的后台进程DIAG消耗很多内存(达到20G),节点1、节点2都出现过次问题。 问题分析:通过对DIAG进程TRACE分析,结合在ORACLE官方后台进行问题、BUG查询匹配&…

uniapp怎么使用jsx

安装vitejs/plugin-vue-jsx npm install vitejs/plugin-vue-jsx -Dvite.config.js配置 import { defineConfig } from "vite"; import uni from "dcloudio/vite-plugin-uni"; import vueJsx from vitejs/plugin-vue-jsxexport default defineConfig({plu…

初始Java篇(JavaSE基础语法)(7)抽象类和接口(下)

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:JavaSE 接上文:初始Java篇(JavaSE基础语法)(7)抽象类和接口(上&#xf…

Netty HTTP2 示例-响应式编程-013

🤗 ApiHug {Postman|Swagger|Api...} = 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱,有温度,有质量,有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Next Generation API Development Platform …

上海亚商投顾:沪指缩量调整 合成生物概念股持续爆发

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 沪指昨日缩量震荡调整,深成指、创业板指均跌超1%。细胞免疫治疗概念股大涨,冠昊生物、…

运营一个在线课堂有哪些基础费用?

我是酷瓜云课堂的作者,对这个问题还是很有心得的。我们的系统是基于腾讯云服务的,下面简单罗列一些基础费用,价格和腾讯云官方有些许出入,仅供参考。 (1)域名 域名注册通常 60 - 80元 / 年,续…