声明式事务的属性~

2023-05-16

说明:本篇文章的代码是基于上篇文章之上的,如有需要,请移至这篇文章

声明式事务的属性:只读,超时,回滚策略:

事务属性:只读

对一个查询操作来说如果我们把它设置为只读,就能明确的告诉数据库,这个操作不涉及写操作,这样数据库就能够针对查询操作来进行优化

设置方法:

@Transactional(readOnly = true)

大家注意看该属性值的默认值为false,那么也就是说,只有在事务中的操作都为查询操作时,才需要将其设置为只读

在这里插入图片描述
注意:只有当事务中的操作都为查询操作时,才能设置事务的只读操作,而如果事务中出现了其他的操作,我们依然将其设置为只读,就会报错

举例:当我们在包含除查询以外的其他操作的事务中,将该事务设置为只读:

在这里插入图片描述

报错如下所示:

在这里插入图片描述

事务属性:超时

事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源,而长时间占用资源,大概率是因为程序运行出现了问题(可能是java程序或者mysql数据库或网络连接等等)

此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行

概括来说就是一句话:超时回滚,释放资源

设置方法:

//将当前的事务执行时间设置为3秒钟,如果超过三秒钟,则直接抛出异常
@Transactional(timeout = 3)

在这里插入图片描述
举例:

在这里插入图片描述

报错如下:事务超时异常

在这里插入图片描述

事务属性:回滚策略

声明式事务默认只针对运行时异常回滚,编译时异常不回滚

可以通过@Transactional中相关属性设置回滚策略

//通常情况下,第一二种我们是不进行设置的,因为所有的运行时异常都会被回滚
rollbackFor属性:需要设置一个Class类型的对象
rollbackForClassName属性:需要设置一个字符串类型的全类名
noRollbackFor属性:需要设置一个Class类型的对象
rollbackFor属性:需要设置一个字符串类型的全类名

在这里插入图片描述
举例:

更新表中的数据,使其余额大于图书价格,如下所示:

在这里插入图片描述

第二步:在购买图书的方法末,手动添加运行时异常,如下所示:

在这里插入图片描述

报错如下:报错内容似乎并没有关于图书购买失败的信息,只抛出了我们手动设置的运行时异常,那么这是代表图书购买成功了吗?

在这里插入图片描述

在数据库中进行查询,发现余额和图书的库存量都没有发生改变,原因是:声明式事务默认只针对运行时异常回滚,我们并没有设置其值,那么就是处于默认情况下

在这里插入图片描述

但上述的数学运算异常好像和我们要处理的业务并没有关系,由此我们可以通过回滚策略进行处理

方法1:

如下所示:

@Transactional(noRollbackFor = {ArithmeticException.class})

noRollbackFor的类型为数组类型[如下所示],因此当其值为多个时,必须使用{}包含,如果其值只有一个,则"{}"可省略

在这里插入图片描述

再次运行结果如下所示:

在这里插入图片描述

好像和上面的结果并没有什么不同,我们再去数据库进行数据的查询,如下所示,图书购买成功,原因是:我们通过@Transactional(noRollbackFor = {ArithmeticException.class})设置当运行时异常为数学运算错误时,不进行回滚操作,因此事务没有回滚

在这里插入图片描述

方法2:

@Transactional(noRollbackForClassName = "java.lang.ArithmeticException")

在这里插入图片描述
由于noRollbackForClassName的类型为字符串,因此,它的值为该异常的全类名

在这里插入图片描述

这种方法的产生效果和第一种完全相同,这里就不演示了

注意:在进行测试时,必须要满足图书是能够被成功购买的条件,因为如果图书都无法被成功购买,那么代码将无法运行到方法末的数学运算

声明式事务的属性之隔离级别:

数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题,一个事务与其他事务隔离的程度称为隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱

隔离级别一共有四种:

读未提交:READ UNCOMMITTED
允许Transaction01读取Transaction02未提交的修改

读已提交:READ COMMITTED
要求Transaction01只能读取Transaction02已提交的修改

可重复读:REPEATABLE READ
确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其他事务对这个字段进行更新

串行化:SERIALIZABLE
确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其他事务对这个表进行添加,更新,删除操作,可以避免任何并发问题,但性能十分低下

各个隔离级别解决并发的能力:

在这里插入图片描述

各种数据库产品对事务隔离级别的支持程度:

在这里插入图片描述

设置属性的隔离级别:

方法:

在这里插入图片描述

//一般将其设置为默认值
@Transactional(isolation = Isolation.DEFAULT)

打开Isolation的源码,如下所示,Isolation是一个枚举类型

在这里插入图片描述

声明式事务的属性之传播行为:

什么是时候之间的传播行为呢?举例来说就是假设现在有两个方法A和B,这两个方法都加上了@Transactional注解,此时这两个方法都有事务的功能,假设现在A事务方法去调用B事务方法,但由于AB两个方法都有事务的功能,因此当A方法调用B事务方法的这个过程中,就会将A方法中的事务传递给B方法,这就造成了B方法现在既有自己本身的事务功能,还有A事务的事务功能,它在实行功能的时候,既可以实行自己本身的额,也可以实行A传递给它的

下面我们就通过具体的实例来演示该功能:

创建实现买单功能的接口:

package spring_txAnnotation.Service;

public interface CheckOutService {
    void Checkout(Integer userId, Integer[] bookId);
}

创建实现买单功能的接口的实现类:

package spring_txAnnotation.Service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import spring_txAnnotation.Controller.BookController;

@Service
public class CheckOutServiceImpl implements CheckOutService{
    @Autowired
    private ServiceBook serviceBook;
    @Autowired
    private CheckOutService checkOutService;
    @Autowired
    private BookController bookController;
    public void buyBook(Integer userId,Integer bookId){
        serviceBook.buyBook(userId,bookId);
    }
    @Transactional
    @Override
    public void Checkout(Integer userId, Integer[] bookId) {//结账方法
       for(Integer bookIds:bookId){
           serviceBook.buyBook(userId,bookIds);
       }
    }
}

将新功能的实现代码加入Controller层:

	@Autowired
    private CheckOutService checkOutService;
    public void Checkout(Integer userid, Integer[] integers) {
        checkOutService.Checkout(userid,integers);
    }

测试类如下所示:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import spring_txAnnotation.Controller.BookController;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:TXannotation.xml")
public class Test1 {
    @Autowired
    private BookController bookController;
    @Test
    public void testBuyBooks(){

        bookController.Checkout(1,new Integer[] {1,2});
    }
}

我们为其新添加了一个事务之后,就导致当前的组件含有两个事务功能,一个是买书操作,一个是结账功能,如下所示:

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

在运行之前,我们先对数据库中的数据进行查询:

在这里插入图片描述

如下所示:

当前用户的余额为100元,只能满足购买一本书的条件,因此,如果执行的是结账操作,那么意味着将购买两本书,显然当前的用户余额是无法满足的,那么就会出现两本书都无法被购买的情况,下面我们运行该程序

报错如下所示:

在这里插入图片描述

此时我们再次访问数据库中的数据,如下所示:

在这里插入图片描述

用户余额和图书库存量都没有发生任何的改变,由此可说明当前执行的是结账的事务功能,因为只要有一本书无法购买,会导致整个事务回滚到最初的状态

那么如果我们想设置使之执行的是本身的买书事务功能呢?

方法:通过@Transactional中的propagation属性设置事务传播行为

打开该属性的源码,如下所示,我们发现该属性的默认值是Propagation.REQUIRED,表示如果当前线程上有已经开启的事务可用,那么就在这个事务中运行

在这里插入图片描述

经过观察,购买图书的方法buyBook0在checkout0中被调用[如下所示],checkout0上有事务注解,因此在此事务中执行。所购买的两本图书的价格为80和50,而用户的余额为100,因此在购买第二本图书时余额不足失败,导致整个checkout()回滚,即只要有一本书买不了,就都买不了

在这里插入图片描述

而当我们将@Transactional中的propagation属性的值设置为Propagation.REQUIRES_NEW表示不管当前线程上是否有已经开启的事务,都要开启新事务。同样的场景,每次购买图书都是在buyBook()的事务中执行,因此第一本图书购买成功,事务结束,第二本图书购买失败,只在第二次的buyBook0中回滚,购买第一本图书不受影响,即能买几本就买几本

设置完毕之后,再次运行,数据库中的数据如下所示:

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

声明式事务的属性~ 的相关文章

  • DBUS入门与C编程

    https blog csdn net weixin 45566765 article details 125028296 一 D Bus简介 1 D Bus是什么 D Bus最主要的用途是在 Linux 桌面环境为进程提供通信 xff0c
  • 模拟IIC——关于模拟IIC的IO口的配置选取推挽输出还是开漏输出,以及是否需要更改IO口输入输出模式和是否需要对IO配置上拉

    在使用模拟IIC的时候 xff0c 观看别人的程序的时候发现了程序之间的一些不一样的地方 代码1 IO方向设置 define SDA IN GPIOB gt MODER amp 61 3 lt lt 9 2 GPIOB gt MODER 6
  • C语言——链表

    C语言 链表 链表是一种基础的数据结构类型 xff0c 一种能够动态维护数据的线性数据表 链表的数据以结点形式存储信息 xff0c 并通过结点之间的指针实现结点之间的衔接 为什么要用链表 xff1f 链表和数组类似 xff0c 但是功能比数
  • 学习记录 | ZigBee协议栈工作流程

    第一次来CSDN记录一下学习过程 xff0c 其实就是笔记啦 之前用Typora 的 但前几天电脑出问题重装系统后打开笔记文件发现照片都打不开了 xff0c 索性想换一种记笔记方式 好啦 以下是正文 xff01 xff01 xff01 对了
  • 学习记录 | ZigBee协议栈实践——串口收发数据

    上次的理论知识学的有点杂乱 今天来跟着例程实践看一看 目录 一 ZigBee协议栈的安装 编译和下载 二 协议栈工作流程 三 串口通信主要代码 1 串口打印 2 串口打印收到的数据 四 实现 五 总结 一 ZigBee协议栈的安装 编译和下
  • 第一次画异形板后的总结感悟

    目录 画原理图前的准备 画PCB的一些好方法 蜂鸣器电路 供电电路 其他电路 杂七杂八的随记要点 总结 像这样的异形板是通过solidworks扫描实物生成的 画原理图前的准备 当然是选购元器件 一般习惯在嘉立创进行选购 选择符合要求 有库
  • 自学物联网ESP第一天

    先简单的使用串口通信AT指令 刚开始不知道用什么开发好 在博客找了很久本来打算用 eclipse 不过突然发现可以用Arduino 不过下载真的好慢 于是开始看一下函数准备一下 一 基本函数 1 setup 函数 Arduino控制器通电或
  • stm32串口发送+接收

    本文章转自B站江科大自化协 一发送 接线图 目标结构 Serial c include 34 stm32f10x h 34 include lt stdio h gt 1移植printf函数 封装sprintf include lt std
  • vscode配置C/C++环境(超详细保姆级教学)

    大一上学期被学长安利了vscode xff0c 但是下载安装后不会配置 xff0c 自己连查带问搞了七八个小时终于配置好了 后面身边很多同学也不会配 xff0c 都来找我帮忙配 xff0c 加上之前自己摸索着配的时候感觉网上没有详细又靠谱的
  • 路由器接口解析

    ensp 接口解析 路由器的CON和AUX con是串口 xff0c 接口电脑串口可以进路由器的命令行查看和设置 一般为设备的控制端口 xff0c Console端口使用配置专用连线直接连接至计算机的串口 xff0c 利用终端仿真程序进行路
  • 解决VSCode写html文件时<!+Enter导入模板快捷键没办法使用的问题

    好久没有写前端了 xff0c 先是用模板快捷键 lt 43 Enter导入模板 xff0c 发现没有办法使用 找到网上一些资料 xff0c VSCode使用 html 5 取代了之前的生成模板快捷键 示例 xff1a 在空白html文本里逐
  • LVGL 之 windows 上 lvgl 模拟器 基于 Visual Studio 搭建方法的简单整理

    mark GUI Guider与lvgl联合仿真 xff08 结合stm32实验进行演示 xff0c 含触摸屏实验计数器与计算器 xff09 https blog csdn net gudao07 article details 12752
  • 初认识stm32 ————每日小总结(串口通信初始化基础操作)

    留下代码 xff0c 日后复习 c文件 include 34 my uart h 34 void my uart init NVIC PriorityGroupConfig NVIC PriorityGroup 2 设置中断优先级分组 RC
  • Sqoop全量导入mysql表数据到HDFS

    我是在三个节点运行的 xff0c 主节点只有namenode和mysql数据库 1 开启服务 具有NameNode和DataNode start all sh 2 进入sqoop的目录下并且输入代码 下面的命令用于从 MySQL 数据库服务
  • 在字符串中查找子字符串

    查找子串 include lt stdio h gt char Search char str1 char str2 char s1 61 str1 char s2 61 str2 char cur 61 str1 while cur s1
  • 基于相机云台周期运动的“远帧差”图像处理算法

    传统的帧差法针对前后两帧或者某几帧进行图像处理 xff0c 一旦相机视角转动 xff0c 就不能获得很好的检测效果 xff0c 我所参与的项目就是一个云台搭载一台红外相机进行取像 xff0c 这样可以大幅度的节约成本 xff0c 但是对图像
  • 深究C语言4.链表和结构体

    目录 一 xff0c 结构体 一 xff0c 结构体的定义 二 xff0c 结构体的概念 1 2 3 4 5 6 三 xff0c 结构变量的使用 1 结构变量的操作符 gt 和 2 结构变量的赋值 3 结构变量作为函数参数 4 结构指针 5
  • 使用c++解析http\https数据遇到的问题(附代码)

    开发环境 xff1a vs2019 系统 xff1a win10 openssl版本 xff1a Win32OpenSSL 3 0 7 访问网页 xff1a www baidu com 先说明以下问题 xff1a c 43 43 在发送ht
  • vector的使用

    vector的介绍 1 vector是表示可变大小数组的序列容器 2 vector就像数组一样 xff0c 也采用的连续空间来存储元素 xff0c 这也意味着可以采用下标对vector的元素进行访问 3 vector与普通数组不同的是 xf
  • Linux系统( Centos 7) 配置与管理Apache服务器实例详细步骤

    Linux系统 xff08 Centos 7 xff09 配置与管理Apache服务器实例详细步骤 服务器centos7 1 1 配置网络 root 64 centos7 vim etc sysconfig network scripts

随机推荐

  • 什么是Cmake和Makefile?

    目录 1 前言 2 什么是Makefile 3 什么是Cmake 4 Cmake的语法规则 1 前言 在学习视觉SLAM十四讲的时候 xff0c 对这个Cmake的概念不太清楚 xff08 笔者是机械方向转到SLAM这个方向的 xff09
  • 创建任务7.24

    创建任务 1 什么是任务 在裸机系统中 xff0c 系统的主体就是 main 函数里面顺序执行的无限循环 xff0c 这个无限循环里面 CPU 按照顺序完成各种事情 在多任务系统中 xff0c 我们根据功能的不同 xff0c 把整个系统分割
  • Linux驱动开发系列:DRM(第十部分)

    https www iotword com 7227 html 一 DRM简介 DRM xff0c 全称Direct Rending Manger 是目前Linux主流的图形显示框架 相比较传统的Framebuffer xff0c DRM更
  • 解决Ubuntu与Virtualbox虚拟机共享文件夹无权限的问题(保姆级)

    目录 使用这个命令后 xff0c 如果不能马上打开共享文件夹 xff0c 需要重启一下ubuntu系统 这样 xff0c 你共享的work文件夹就能在Ubuntu系统访问了 声明 CSDN 64 m0 637799558昵称更改为 64 孤
  • char类型与int类型的转换

    在c语言中 xff0c char类型与int类型可以转换 xff0c 如何转换我在此做一个粗略的总结 首先是char转换为int include lt stdio h gt int main char a a 61 110 int c 61
  • C语言中字符串大小与长度的区分

    字符串大小和字符串长度不同 xff1a 字符串大小指该字符串占用多少空间 字符串长度指该字符串的字符个数
  • 【字符串函数】strcat的使用及原理

    1 strcat函数的函数声明 char strcat char Destination const char Source 2 strcat函数的头文件 include lt string h gt 3 strcat函数的使用 strca
  • 【DRM】DRM Display Driver Guide

    https zhuanlan zhihu com p 534267979 目录 收起
  • TCP协议

    1 TCP协议的可靠传输 我们知道TCP协议的特点有 有连接 可靠传输 面向字节流 全双工 其中连接 面向字节流和全双工在 网络编程 该文章中详细说明了 而要深入了解TCP协议 了解可靠传输也是重中之重 可靠传输也是TCP协议的一大特点 那
  • c/c++程序运行不出结果?

    1 xff0c 条件语句未执行 在运行过程中 xff0c 用到if或while等条件语句 xff0c 条件之后的语句没有执行就结束了 xff0c 且输出变量也未初始化 xff0c 当然就输出不了任何东西了 xff1b 2 xff0c 变量未
  • 【解救ROS】关于ros机器人(小车)动态调试PID参数

    1 打开终端 xff0c 连接树莓派 ssh clbrobot 64 clbrobt 2 打开底盘节点 roslaunch clbrobot bringup launch 3 再打开一个终端 ssh clbrobot 64 clbrobt
  • 十进制转十六进制(C语言)

    首先要注意输入非负整数的范围 xff1a 这里用long表示 xff1b long 取值 2147483648 2147483647 include lt stdio h gt int main long n int i 61 0 j ch
  • C语言之数组的定义及其使用方法

    作者 xff1a 从未止步 博客主页 xff1a 从未止步的博客 专栏 xff1a 和我一起学C 语录 xff1a Every day is a second chance 行动是理想最高贵的表达 xff0c 给大家介绍一款超牛的斩获大厂o
  • python之常量的定义

    常量 xff1a 与C语言不同的是 xff0c python中并没有用来修饰常量的修饰符 xff0c 在python中可以通过自定义实现常量 xff0c 要求常量的标识符必须全是大写字母 xff0c 且该值不能被修改 举例 xff1a PI
  • C语言之根据摄氏温度求华氏温度

    求摄氏温度26 C对应的华氏温度 计算公式 xff1a f 61 9 c 5 43 32 xff0c 式中 xff1a c表示摄氏温度 xff0c f表示华氏温度 输入输出示例 xff1a celsius 61 26 fahr 61 78
  • python文件的操作和异常之异常

    异常 xff1a python使用称为异常的特殊类对象来管理程序执行期间发生的错误 xff0c 每当发生让python不知所措的错误时 xff0c 他都会创建一个异常的对象 如果你编写了处理该异常的代码 xff0c 程序将继续进行 xff0
  • Java---抽象类和接口

    抽象类 xff1a 抽象类的基本概念 xff1a 在面向对象的概念中 xff0c 所有的对象都是通过类来描述并创建的 xff0c 但是有一种特殊的类 xff0c 并不能用完整的信息来描述一个具体的对象 xff0c 这样的类就是抽象类 xff
  • 通过基于注解的声明式事务实现事务功能~

    编程式事务 xff1a 事务功能的相关操作全部通过自己编写代码来实现 xff1a span class token class name Connection span conn span class token operator 61 s
  • 《DRM 专栏》| 彻底入门 DRM 驱动

    https cloud tencent com developer article 2021477 前面的 DRM 应用程序系列文章中 xff0c 我们学习了如何使用 libdrm 接口编写 DRM 应用程序 本篇我们将进入一个全新的世界
  • 声明式事务的属性~

    说明 xff1a 本篇文章的代码是基于上篇文章之上的 xff0c 如有需要 xff0c 请移至这篇文章 声明式事务的属性 xff1a 只读 xff0c 超时 xff0c 回滚策略 xff1a 事务属性 xff1a 只读 对一个查询操作来说