理清Spring事务的核心关键类

news2024/11/25 20:20:16

在spring事务源码的内部,会有几个比较核心关键的类,虽然这基本上都是源码内部才使用到的类,但是有时候我们要对其做一些改造的时候免不了要去使用到这些类,并且这些类在spring事务内部都是起到关键的作用,对了解spring事务源码的帮助比较大,所以下面我们重点就来理解下这些关键类

事务管理器PlatforomTransactionManager

事务管理器,该接口是spring事务的核心实现接口,它提供了三个方法:

TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
      throws TransactionException;

void commit(TransactionStatus status) throws TransactionException;

void rollback(TransactionStatus status) throws TransactionException;
  • getTransaction

获取一个“逻辑”事务。所谓的“逻辑”事务其实就是spring事务的概念,并不是一个实际上数据库的物理事务

  • commit

提交事务,该方法会去实际提交一个实际的数据库事务 

  • rollback

回滚事务,该方法会去回滚一个实际的数据库事务 

对于不同的类型的spring事务,都会有对应的事务管理器实现,比如最常用的spring事务管理器就是DataSourceTransactionManager,还有支撑JPA实现的JpaTransactionManager 

事务对象 

 不同的事务管理器有不同的事务对象实现,比如DataSourceTransactionManager所对应的事务对象就是DataSourceTransactionObject。当通过事务管理器的getTransaction方法去获取一个spring事务的时候,都会创建一个事务对象,而这个事务对象会包含一个实际的数据库连接对象,spring事务对象与实际的数据库事务之间的关系图大致如下:

 

从上图中可以看到,只要我们创建一个spring事务,对应就都会创建一个spring事务对象,而这个事务对象中封装的就是实际的数据库事务信息(比如其中最核心的connection),只不过根据不同的事务传播级别,创建出来的事务对象中的数据库事务信息有可能是复用线程上下文中已存在的,又或者是一个自己新创建的数据库事务。说到这里,大家应该都知道事务对象在spring事务中一个很重要的类了,那么具体的事务对象是哪个?这里我们主要关注我们最常用的DataSourceTransactionObject 

(1)JdbcTransactionObjectSupport

JdbcTransactionObjectSupport是所有事务对象的基类

public abstract class JdbcTransactionObjectSupport implements SavepointManager, SmartTransactionObject {

   /**
    * 连接对象包装类
    */
   @Nullable
   private ConnectionHolder connectionHolder;

   /**
    * 原本数据库的隔离级别
    */
   @Nullable
   private Integer previousIsolationLevel;

   /**
    * 当前事务是否只读
    */
   private boolean readOnly = false;

   private boolean savepointAllowed = false;

    ......
}

其中它有一个最重要的字段就是ConnectionHolder,ConnectionHolder中就封装数据库连接对象connection 

(2)DataSourceTransactionObject

/**
 * 该对象是由DataSourceTransactionManager这个事务管理器创建的具体事务对象,
 * 每次调用事务方法(无论是否在同一个事务中)都会生成一个DataSourceTransactionObject对象,里面主要是包含了connection连接对象
 */
private static class DataSourceTransactionObject extends JdbcTransactionObjectSupport {

   /**
    * 当前事务对象所持有的connection对象是否是由当前事务对象所创建的
    * (在同一个事务中,如果事务方法a调用事务方法b,事务方法a和事务方法b都会各自创建一个DataSourceTransactionObject对象,
    * 不过进来事务方法a的时候就会创建一个新的connection对象,而进来事务方法b的时候会复用事务方法a方法创建的连接对象,也就是两个不同的DataSourceTransactionObject对象使用同一个connection对象)
    */
   private boolean newConnectionHolder;

   /**
    * 是否必须要恢复数据库为自动提交
    */
   private boolean mustRestoreAutoCommit;
   
   ......
}

 DataSourceTransactionObject中最重要的就是newConnectionHolder这个字段,该字段表示的就是当前这个事务对象中包含的connection是否是由它自己创建的,根据上面的流程图我们可以知道,在每一次创建一个spring事务对象的时候,会去看一下线程上下文中是否有事务了,然后再结合spring事务的传播级别去判断是否需要创建一个新的connection,所以如果是复用线程上下文中的事务,则newConnectionHolder就为false,反之,则为true

TransactionStatus 

TransactionStatus表示一个spring的事务状态,默认的实现类是DefaultTransactionStatus,当我们每一次去创建一个spring事务的时候,通过上面知道都会创建一个spring事务对象,而除了事务对象之外,还会创建一个TransactionStatus对象,其中TransactionStatus对象会把事务对象包装进去,然后再通过TransactionStatus接口提供的方法去对包装的事务对象进行获取其事务状态信息等

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

   boolean hasSavepoint();

   @Override
   void flush();
}

TransactionStatus接口继承了TransactionExecution接口以及SavepointManager接口 

 

public interface TransactionExecution {

   /**
    * 当前事务是否是一个新事务
    */
   boolean isNewTransaction();

   /**
    * 仅设置事务回滚。这会指示事务管理器,事务的唯一可能结果可能是回滚,而不是抛出异常,从而触发回滚
    */
   void setRollbackOnly();

   /**
    * 返回事务是否已标记为仅回滚
    */
   boolean isRollbackOnly();

   /**
    * 事务是否已经完成,无论是已提交还是已回滚都算是已完成
    */
   boolean isCompleted();

}
public interface SavepointManager {

   Object createSavepoint() throws TransactionException;

   void rollbackToSavepoint(Object savepoint) throws TransactionException;

   void releaseSavepoint(Object savepoint) throws TransactionException;
}

其中TransactionExecution接口主要就是负责提供对事务的一些处理方法,比如判断事务是否是一个新的事务,判断是否设置了仅回滚状态,判断事务是否已经完成等;而SavepointManager接口见名知意就是与保存点相关的接口,分别提供了创建保存点,回滚保存点,释放保存点这三个方法

TransactionDefinition 

TransactionDefinition接口就是用来描述要事务信息的,默认的实现是DefaultTransactionDefinition,每当我们要去创建一个spring逻辑事务的时候,我们首先要知道的是创建出来的事务信息是什么,就好比说你要别人造一个房子,你就需要把这个房子的设计图给到别人,而对应来说TransactionDefinition的作用就去描述一个事务属性,我们根据这个事务属性去创建出对应的spring事务。默认实现的DefaultTransactionDefinition的核心属性如下:

/**
 * 事务传播级别
 */
private int propagationBehavior = PROPAGATION_REQUIRED;

/**
 * 事务隔离级别
 */
private int isolationLevel = ISOLATION_DEFAULT;

/**
 * 事务超时时间
 */
private int timeout = TIMEOUT_DEFAULT;

/**
 * 事务是否是只读的
 */
private boolean readOnly = false;

/**
 * 事务的名称
 */
@Nullable
private String name;

 事务同步器TransactionSynchronization

该类应该是最接近于我们平时开发所要用到的类了,通过该接口我们能够监控spring事务的各个极端,比如在spring事务提交,或者是事务回滚,事务挂起等状态的时候,我们就可以通过该接口来做一些我们想要进行扩展的事情,该接口提供了对spring事务各个阶段的接口方法,对于该组件的详细文章可以到另一篇文章聊聊Spring事务同步器TransactionSynchronization

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

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

相关文章

[2023-09-13]使用EXPDP/IMPDP迁移数据库后统计信息引起的性能问题

问题描述: 客户在使用expdp/impdp迁移数据库完成后,在新环境收集统计信息,但是在迁移完成的当天中午,好多SQL语句执行变慢,执行计划发生了改变,下面通过案例来说明。 1、准备数据 scott用户下创建test表&…

进程控制再学习

0.“开两个终端窗口” 因为学校用的虚拟机,得用终端登录,不能像shell一样直接复制窗口。 我们只需要登录两次就可以了(方便监视) 1.ps 1.循环ps while :;do ps -f;ps -ef|grep zombie;done 每秒打印一次: while :…

基于SSM+Vue的校园教务系统的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用Vue技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

报修工单系统如何提升维修维保工作效率?

在日常的报修维修工作中,我们经常会遇到一些挑战。其中数据分析是一项艰巨的任务,因为我们需要处理大量的数据并从中提取有价值的信息。维修工单的统计也是一个复杂的过程,需要对工单进行分类和整理,以便更好地了解工作的进度和效…

sudo+vim+g++/gcc+makefile+进度条

目录 一、信任表中加入指定的普通用户(使其能使用sudo) 二、vim的使用 (一)基本概念 1. 正常/普通/命令模式(Normal mode) 2. 插入模式(Insert mode) 3. 末行模式(last line mode) (二)vim正常模式…

国庆中秋特辑(一)浪漫祝福方式 用循环神经网络(RNN)或长短时记忆网络(LSTM)生成祝福诗词

目录 一、使用深度学习中的循环神经网络(RNN)或长短时记忆网络(LSTM)生成诗词二、优化:使用双向 LSTM 或 GRU 单元来更好地捕捉上下文信息三、优化:使用生成对抗网络(GAN)或其他技术…

根据keypoint生成heatmap

这里keypoint是有类别的,生成的heatmap是每个通道对应每个类别的heatmap 第一种会比较慢,第二种会比较快 第一种 def generate_heatmap(heatmap_size, sigma, class_num, keypoints, normalization): """generate gaussian heatmap:…

0.96寸OLED屏显示测试和代码详细分析SPI通信

第一次尝试点亮 程序代码地址,密码:1234。 买了一个两色的oled,然后下载了资料,手里有一个8266的arduino,所以为了方便就直接用了。使用arduino主要原因,单片机keil太大,来回找文件修改引脚比较麻烦。实际…

在ubuntu20下使用花生壳映射vscode SSH

1、在ubuntu20下安装花生壳 下载花生壳:花生壳客户端官方下载 - 贝锐花生壳官网 选择ubuntu 或者 wget "https://dl.oray.com/hsk/linux/phddns_5.2.0_amd64.deb" -O phddns_5.2.0_amd64.deb 安装 :sudo dpkg -i phddns_5.2.0_amd64.deb" -O phddns…

【sgGoogleTranslate】自定义组件:基于Vue.js用谷歌Google Translate翻译插件实现网站多国语言开发

sgGoogleTranslate源码 <template><div :id"$options.name"> </div> </template> <script> export default {name: "sgGoogleTranslate",props: ["languages", "currentLanguage"],data() {return {//…

图解曲线积分的对称性

1.图解曲线积分的对称性 1.1 第一类曲线积分的一般对称性 二重积分、三重积分、第一类曲线积分、第一类曲面积分的一般对称性其原理都类似 平面曲线和空间曲线的原理一样&#xff0c;以下内容以空间曲线为例 图中所示为积分区域 Γ \Gamma Γ&#xff0c;函数 f ( x , y , z…

利用 Python PyPDF2库轻松提取PDF文本(及其他高级操作)

当需要从PDF文件中提取文本时&#xff0c;Python中的PyPDF2库是一个非常有用的工具。无论您是需要分析PDF文档中的内容还是需要在文档中搜索特定的信息&#xff0c;PyPDF2都可以帮助您轻松实现这些任务。 在本文中&#xff0c;我们将探讨如何使用PyPDF2库提取PDF文件中的文本&…

vue学习之vue cli创建项目

安装 node.js https://nodejs.org/en 安装 vue cli npm install -g @vue/cli --registry=https://registry.npm.taobao.org创建项目 执行创建命令,回车vue create vue-cli-learning选择 “Manually select features”,回车 “空格” 关闭 Linter / Formatter 选项,回车

开源库源码分析:OkHttp源码分析(二)

开源库源码分析&#xff1a;OkHttp源码分析&#xff08;二&#xff09; 导言 上一篇文章中我们已经分析到了OkHttp对于网络请求采取了责任链模式&#xff0c;所谓责任链模式就是有多个对象都有机会处理请求&#xff0c;从而避免请求发送者和接收者之间的紧密耦合关系。这篇文章…

【数据结构】链表面试题

203.移除链表元素 206.反转链表 876.链表的中间结点 牛客.链表中倒数第k个结点 21.合并两个有序链表 牛客.链表分隔 牛客.链表的回文结构 160.相交链表 141.环形链表 142.环形链表2 1. 移除链表元素 题目描述 思路&#xff1a; 定义一个指针cur遍历整个链表&#xff0c;一个ta…

阿里云 linux 的nginx 配置uni-app的H5前端项目vue,后端接口阿里云。

背景 vue项目调用接口是阿里云的&#xff0c;H5网站也要部署到阿里云&#xff0c;2个不同的服务器&#xff0c;需要做nginx部署与api代理。 端口配置 首先当然是买个阿里云服务器&#xff0c;这里是配置是linux系统&#xff0c;配置访问的域名 &#xff0c;再接着&#xff1…

【李沐深度学习笔记】数据操作

本课观看地址 数据操作p1 N维数组样例 N维数组是机器学习和神经网络的主要数据结构 1-d向量就是样本的各特征抽象成一个向量&#xff1b;2-d矩阵的每一行是一个样本&#xff0c;每一行都是一个样本的特征向量 3-d可以表示RGB图片&#xff0c;RGB图像是一个三维数组&#xff…

MarkText如何实现图床-解决md上传到csdn图片不显示的问题

安装picgo-core-这样做无法自动上传截图 npm install picgo -g配置-此处以github为例 picgo set uploader github生成token settings>Developer settings>Personal access tokens>Token(classic) 配置MarkText 点击左下角的设置在弹出的窗口后选择左边的Image在右…

学习Bootstrap 5的第十三天

目录 提示框 如何创建提示框 实例 指定提示框的位置 实例 弹出框 如何创建弹出框 实例 指定弹出框的位置 实例 关闭弹出框 实例 提示框 提示框是一个小小的弹窗&#xff0c;在鼠标移动到元素上显示&#xff0c;鼠标移到元素外就消失。 如何创建提示框 Bootstrap…

VIRTIO-SCSI代码分析(2)VIRTIO 驱动分析

QEMU模拟出VIRTIO SCSI设备后&#xff0c;在虚拟机中呈现SCSI设备和PCIE设备。而在虚拟机中&#xff0c;PCIE设备与VIRTIO PCI驱动匹配触发virtio_pci_probe()注册生成virtio设备&#xff0c;而virtio设备与虚拟机中的virtio驱动匹配触发对应probe函数最终注册对应的驱动。 这里…