5 - 声明式事务

传统事务流程:

Connection connection = JdbcUtils.getConnection();
try {
    //1. 先设置事务不要自动提交
    connection.setAutoCommit(false);
    //2. 进行各种 crud
    //多个表的修改,添加 ,删除
    select from 商品表 => 获取价格
    //修改用户余额
    update ...
    //修改库存量
    update
    //3. 提交
    connection.commit();
} catch (Exception e) {
    //4. 回滚
    conection.rollback();
}

使用 Spring 的声明式事务处理, 可以将上面三个子步骤分别写成一个方法,然后统一管理

1. 使用实例

1.1 创建 src\tx_ioc.xml 文件

<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${jdbc.userName}"></property>
    <property name="password" value="${jdbc.password}"></property>
    <property name="driverClass" value="${jdbc.driverClass}"></property>
    <property name="jdbcUrl" value="${jdbc.url}"></property>
</bean>
<!-- 配置 JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!-- 将上面的数据源分配给 jdbcTemplate -->
    <property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务管理器 -->
<bean id="dataSourceTransactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启基于注解的声明式事务功能 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
<!-- 加入自动扫描包 dao -->
<context:component-scan base-package="com.hspedu.spring.tx.dao"/>

1.2 修改对象

修改 GoodsService.java,加入声明式事务注解

@Transactional
public void buyGoodsByTx(int user_id, int goods_id, int num) {
    //查询到商品价格
    Float goods_price = goodsDao.queryPriceById(goods_id);
    //购买商品,减去余额
    goodsDao.updateBalance(user_id, goods_price * num);
    //模拟一个异常, 会发生数据库数据不一致现象
    // int i = 10 / 0;
    //更新库存
    goodsDao.updateAmount(goods_id, num);
}

1.3 声明式事务机制

  • 使用@Transactional 可以进行声明式事务控制;即将标识的方法中的,对数据库的操作作为一个事务管理
  • @Transactional 底层使用的仍然是AOP机制
  • 底层是使用动态代理对象来调用buyGoodsByTx

执行流程:

  1. 在执行buyGoodsByTx() 方法 先调用 事务管理器的 doBegin(),主要是将自动提交关掉  
  2. 然后调用 buyGoodsByTx()
  3. 如果执行没有发生异常,则调用 事务管理器的 doCommit()
  4. 如果发生异常 调用事务管理器的 doRollback()

2. 事务的传播机制

当有多个事务处理并存时,如何控制?

2.1 事务的传播机制种类

  • REQUIRED:如果现在有事务在运行,当前的方法就是在这个事务内运行
  • REQUIRED_NEW:当前方法必须新启动一个事务,在自己的事务内运行
  • SUPPORTS:如果现在有事务在运行,当前方法就在这个事务内运行,否则它可以不运行在事务中
  • NOT_SUPPORTE:当前方法不应该运行在事务内,如果有事务,该方法将挂起
  • MANDATORY:当前方法必须运行在事务内,如果没有运行在事务,则抛出异常
  • NEVER:当前方法不可以运行在事务内,如果运行在事务,则抛出异常
  • NESTED:如果现在有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则就启动一个新的事务,并运行在自己的事务里

重点分析 REQUIRED 和 REQUIRED_NEW

1)REQUIED(默认事务传播机制)

2)REQUIRES_NEW 

 3)事务的传播机制的设置方法

 4)例子

如果设置为 REQUIRES_NEW:

buyGoods2 如果错误,不会影响到 buyGoods(),即它们的事务是独立的

如果设置为 REQUIRED:

buyGoods2 和 buyGoods 是一个整体,只要有方法的事务错误,那么两个方法都不会执行成功.!


3.  事务的隔离级别

这个概念参考 MySQL

3.1 说明

默认的隔离级别, 就是 mysql 数据库默认的隔离级别 一般为 REPEATABLE_READ

查看数据库默认的隔离级别:

SELECT @@global.tx_isolation

3.2 事务隔离级别的设置及测试

1)默认

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void buyGoodsByTxISOLATION(int user_id, int goods_id, int num) {
    //查询到商品价格
    Float goods_price = goodsDao.queryPriceById(goods_id);
    System.out.println("第一次读取的价格 =" + goods_price);
    //测试一下隔离级别,在同一个事务中,查询一下价格
    goods_price = goodsDao.queryPriceById(goods_id);
    System.out.println("第二次读取的价格 =" + goods_price);
}

过程:在读完第一次数据后,通过 mysql 进行修改该数据

结果:两次读取到的价格是一样的,不会受到 MySQL 修改影响

2)READ_COMMITTED 隔离级别情况

语法:

 结果:两次读取到的价格是不一样的,数据是会受到 MySQL 修改影响


4. 事务的超时回滚

目的:如果一个事务执行的时间超过某个时间限制,就让该事务回滚

语法:

超出时间会抛出异常,事务回滚,原来的操作撤销 

注:

  • timeout = 2 表示 buyGoodsByTxTimeout 如果执行时间超过了2秒, 该事务就进行回滚
  • 如果没有设置 timeout, 默认是 -1,表示使用事务的默认超时时间,或者不支持

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

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

相关文章

Jetbrains ai assistant激活后仍无法使用,怎么回事?

用正式的ai assistant激活码激活后仍然无法使用 首先获取了ai assistant激活码&#xff0c;激活后如下 地址&#xff1a;https://web.52shizhan.cn 上图是已经激活成功了&#xff0c;但是在右侧这里打开ai assistant不可用 点击开始使用ai assistant 出错 以上是用了ai as…

排序——归并排序

文章目录 基本思想递归版本思路代码实现 非递归版思路代码实现 特性结果演示 基本思想 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。将已有序的子…

智能合约介绍

莫道儒冠误此生&#xff0c;从来诗书不负人 目录 一、什么是区块链智能合约? 二、智能合约的发展背景 三、智能合约的优势 四、智能合约的劣势 五、一些关于智能合约的应用 总结 一、什么是区块链智能合约? 智能合约&#xff0c;是一段写在区块链上的代码&#xff0c;一…

HNU-算法设计与分析-实验2

算法设计与分析实验2 计科210X 甘晴void 202108010XXX 目录 文章目录 算法设计与分析<br>实验21 用动态规划法实现0-1背包问题重述想法代码验证算法分析 2 用贪心算法求解背包问题问题重述想法代码验证算法分析 3 半数集问题&#xff08;实现题2-3&#xff09;问题重述…

【详解】Java集合框架

文章目录 集合1、Collection1.1、List1.2、Queue & Deque1.2.1、Stack 1.3、Set 集合 Java 集合&#xff0c;也称为容器&#xff0c;主要由两大接口&#xff08;Interface&#xff09;派生出来的&#xff0c;Collection 和 Map Collection 用来存放单一元素&#xff08;单…

非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (II, Python 简单实例)

Title: 非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (II, Python 简单实例) 姊妹博文 非线性最小二乘问题的数值方法 —— 从高斯-牛顿法到列文伯格-马夸尔特法 (I) 文章目录 0.前言1. 最优问题实例2. 列文伯格-马夸尔特法 (Levenberg-Marquardt Me…

Mindspore 公开课 - CodeGeeX

CodeGeeX: 多语言代码生成模型 CodeGeeX 是一个具有130亿参数的多编程语言代码生成预训练模型。CodeGeeX采用华为MindSpore框架实现&#xff0c;在鹏城实验室“鹏城云脑II”中的192个节点&#xff08;共1536个国产昇腾910 AI处理器&#xff09;上训练而成。截至2022年6月22日&…

非常好用的Mac清理工具CleanMyMac X 4.14.7 如何取消您对CleanMyMac X的年度订购

CleanMyMac X 4.14.7是Mac平台上的一款非常著名同时非常好用的Mac清理工具。全方位扫描您的Mac系统&#xff0c;让垃圾无处藏身&#xff0c;您只需要轻松单击2次鼠标左键即可清理数G的垃圾&#xff0c;就这么简单。瞬间提升您Mac速度。 CleanMyMac X 4.14.7下载地址&#xff1a…

WEB 3D技术 three.js 3D贺卡(1) 搭建基本项目环境

好 今天 我也是在网上学的 带着大家一起来做个3D贺卡 首先 我们要创建一个vue3的项目、 先创建一个文件夹 装我们的项目 终端执行 vue create 项目名称 例如 我的名字想叫 greetingCards 就是 vue create greetingcards因为这个名录 里面是全部都小写的 然后 下面选择 vue3 …

CSS实现平行四边形

1、为什么实现平行四边形 在日常开发过程中&#xff0c;有些时候我们可以会遇到一种情况&#xff0c;如可视化大屏中要求我们横线实现对应的进度条&#xff0c;但进度条的内容是由无数个平行四边形组装类似于进度条的形式&#xff0c;那么我们就需要使用CSS来进行对应的实现。 …

Python: vars()详细解释

vars() 是一个内置函数&#xff0c;用于返回一个对象的 __dict__ 属性。它接受一个对象作为参数&#xff0c;如果省略参数&#xff0c;它返回当前局部作用域的字典。 具体而言&#xff0c;vars() 的行为取决于参数的类型&#xff1a; 1. 没有参数&#xff1a; 如果没有提供参…

【MATLAB】EEMD+FFT+HHT组合算法

代码原理 EEMD&#xff08;经验模态分解&#xff09;FFT&#xff08;快速傅里叶变换&#xff09;HHT&#xff08;希尔伯特-黄变换&#xff09;组合算法是一种常用的信号处理和分析方法。这个组合算法包含了EEMD、FFT和HHT三个步骤&#xff0c;可以用于处理非线性和非平稳信号。…

【网络取证篇】Windows终端无法使用ping命令解决方法

【网络取证篇】Windows终端无法使用ping命令解决方法 以Ping命令为例&#xff0c;最近遇到ping命令无法使用的情况&#xff0c;很多情况都是操作系统"环境变量"被改变或没有正确配置导致—【蘇小沐】 目录 1、实验环境&#xff08;一&#xff09;无法ping命令 &a…

嵌入式学习-网络编程-Day2

思维导图 tcp通信流程 udp通信流程 作业1 写一个基于TCP协议的客户端来控制RobArm机械臂 代码 #include <myhead.h> #define SER_PORT 8888 #define SER_IP "192.168.122.71" #define CLI_PORT 6666 #define CLI_IP "192.168.122.36"int main(int…

FPN网络的实现原理详解

1 前言 FPN网络是一种常见的特征融合模块&#xff0c;在很多模型中都有运用&#xff0c;今天我们就结合代码和论文详细的搞清楚它到底是怎么一回事。 2 原理 原理直接看这一张图就可以了&#xff0c;很直观主要就是把对不同层的特征进行融合&#xff0c;重点还是在于代码的理…

MOS管驱动电流计算以及分立器件驱动电路

自记&#xff1a; 1.先根据mos数据手册查找参数&#xff0c;计算电流&#xff1b; 2.分立器件驱动电路图&#xff1b; 3.分立器件选择 仔细学&#xff0c;能看懂&#xff01; 1.计算电流&#xff1a; 2.分立器件驱动电流&#xff1a;两种&#xff0c;第一种反向&#xff0c…

实践学习PaddleScience飞桨科学工具包

实践学习PaddleScience飞桨科学工具包 动手实践&#xff0c;在实践中学习&#xff01;本项目可以在AIStudio平台一键运行&#xff01;地址&#xff1a;https://aistudio.baidu.com/projectdetail/4278591 本项目第一次执行会报错&#xff0c;再执行一次即可。若碰到莫名其妙的…

Linux操作系统——重定向与缓冲区

1.理解一下struct file内核对象 上一篇文章&#xff08;文件详解&#xff09;我们一直在谈&#xff0c;一个文件要被访问就必须要先被打开&#xff0c;打开之前就必须要先把文件加载到内存&#xff0c;同时呢我们的操作系统为了管理文件也会为我们的文件创建相对应的struct fi…

低频信号发生器

前言 最近我快期末考试了&#xff0c;有点忙着复习。没时间写文章&#xff0c;不过学会了焊接 挺开心的所以买几套。 焊得怎么样这就是我们今天故事的主角“低频信号发生器”&#xff08;由于要用到所以这是购买链接&#xff09; 好&#xff0c;故事开始&#xff1a; 如何将…

基于Java (spring-boot)的社团管理系统

一、项目介绍 系统管理员的功能概述&#xff1a; ①用户管理 a.注册用户账户 当一个新用户注册时&#xff0c;用户填写基本信息并上传。用户基本信息包括账号、 姓名、密码、手机、地址等信息。 b.用户信息管理 管理员可以查看系统所有用户的基本信息&#xff0c;并修改和…