Spring-TX 事务

news2024/11/20 16:33:08

目录

一、事务的种类

二、Spring事务管理器

三、事务注解使用

四、事务注解属性


一、事务的种类

1.编程式事务

所谓编程式事务就是用代码手写事务,包含了事务的开始,具体事务,事务的提交和事务的回滚。在这期间就会产生一些冗余问题,比如事务的开始,事务的提交,事务的回滚。都是一些重复的代码,如果在事务很多的情况下,代码量会比较庞大,并且十分臃肿。

传统的编程式事务

Connection conn = ...;

try {
    // 开启事务:关闭事务的自动提交
    conn.setAutoCommit(false);
    // 核心操作
    // 业务代码
    // 提交事务
    conn.commit();

}catch(Exception e){

    // 回滚事务
    conn.rollBack();

}finally{

    // 释放数据库连接
    conn.close();

}

2.声明式事务

声明式事务是指使用注解或 XML 配置的方式来控制事务的提交和回滚。

开发者只需要添加配置即可, 具体事务的实现由第三方框架实现,避免我们直接进行事务操作!

优点:

使用声明式事务可以将事务的控制和业务逻辑分离开来,提高代码的可读性和可维护性。

区别:

  • 编程式事务需要手动编写代码来管理事务
  • 而声明式事务可以通过配置文件或注解来控制事务。

二、Spring事务管理器

2.1事务管理器介绍

使用SpringTx时候由于持久层框架的不同(如JDBC、JDBCTemplate、Mybatis等)使得Spring的事务管理接口有多个对应的实现类分别如下

  • spring-tx: 包含声明式事务实现的基本规范(事务管理器规范接口和事务增强等等)
  • spring-jdbc: 包含DataSource方式事务管理器实现类DataSourceTransactionManager
  • spring-orm: 包含其他持久层框架的事务管理器实现类例如:Hibernate/Jpa等

由于一般使用MyBatis,JDBC,JDBCTemplate都是使用DataSourceTransactionManager类。DataSourceTransactionManager的常用方法如下

方法名描述
doBegin()开启一个新的事务。
doSuspend()用于挂起当前事务上下文,并且暂停现有的事务。
doResume()恢复挂起的事务上下文,并继续已有的事务。
doCommit()提交当前事务。
doRollback()回滚当前事务。

 2.2事务管理器配置

需要先导入对应的依赖

<!-- 声明式事务依赖-->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>6.0.6</version>
  </dependency>

在配置类中的具体配置

@Configuration
@ComponentScan("com.alphamilk")
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement
public class JavaConfig {

    @Value("${alphamilk.url}")
    private String url;
    @Value("${alphamilk.driver}")
    private String driver;
    @Value("${alphamilk.username}")
    private String username;
    @Value("${alphamilk.password}")
    private String password;

    @Bean
    //druid连接池
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driver);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
    @Bean
    //JDBCTemplate
    public JdbcTemplate jdbcTemplate( ){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource());
        return jdbcTemplate;
    }
//    设置TransactionManger事务管理接口
    @Bean
    public TransactionManager transactionManager(DataSource dataSource){
//        创建DataSourceTransaction对象
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
//        配置对应的数据源
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

三、事务注解使用

使用的注解

注解描述
@EnableTransactionManagement启用事务管理。需要在配置类上添加该注解。
@Transactional标记需要事务管理的方法或类。可以在方法级别或类级别使用

使用的范围:类或是方法

当作用在方法上时候,其对应的仅仅是对某一个具体的事务声明。

案例代码:

@Service
public class StudentService {

    @Autowired
    private StudentDao studentDao;

    @Transactional
    public void changeInfo(){
        studentDao.updateAgeById(20,1);
//        设置异常,如果发生异常,则事务会自动回滚,即上面代码虽然执行,但是不会提交
        int i = 1/0;
        System.out.println("-----------");
        studentDao.updateNameById("test2",1);
    }
}

当作用在类上的时候,对类上所有的方法进行事务声明

案例代码:

@Service
@Transactional
public class StudentService {

    @Autowired
    private StudentDao studentDao;

    public void changeInfo(){
        studentDao.updateAgeById(20,1);
        System.out.println("-----------");
        studentDao.updateNameById("test2",1);
    }
}

注意:在使用事务注解的时候,配置种记得需要设置开启事务声明的注解,并且注意@Transactional注解同时作用于类和方法上时候,作用在类上的注解会将类上的注解覆盖。即不享受类上事务声明的效果

@Configuration
@ComponentScan("com.alphamilk")
@PropertySource("classpath:jdbc.properties")
//开启事务声明注解
@EnableTransactionManagement

四、事务注解属性

事务注解中有多种属性,分别是只读模式,超出时间,,,。并且每一个属性都有其相应的异常

1.只读模式/设置

属性名称:readOnly (默认为false)

属性解释

当处于readOnly开启状态的时候,只能进行读取信息的操作,无法执行修改的操作,这么做可以提高事务的效率。

案例代码:

@Transactional(readOnly = true)
    public void changeInfo(){
        studentDao.updateAgeById(20,1);
        System.out.println("-----------");
        studentDao.updateNameById("test2",1);
    }

对应的事务异常(如果在只读状态下进行了非只读操作会引发下面的异常)


2.超时时间并回滚

属性名称:timeout

属性解释,在注解后同各国timeout = value实现如果超过value秒则会触发对应的异常。注意默认-1,表示无限长的限制时间。

案例代码:

@Service
public class StudentService {

    @Autowired
    private StudentDao studentDao;

    @Transactional(timeout = 3)
    public void changeInfo(){
        //非只读方法
        studentDao.updateAgeById(20,1);
        System.out.println("-----------");
        //设置事务时间超过最长限制时间
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        studentDao.updateNameById("test2",1);
    }
}

对应的事务异常(如果在超过事务的处理时间时候会引发下列异常)


3.指定事务异常

我们知道Exception异常有两个子类 分别是RuntimeException与IOException,而@Transaction异常在默认情况下只能够捕捉Runtime异常时候才会进行事务回滚,而如果发生了IOException异常则不会进行事务回滚

属性名称:rollbackFor (指定异常回滚)noRollBackFor(在指定异常范围内不进行回滚,基本不会使用)

案例代码:

@Service
public class StudentService {

    @Autowired
    private StudentDao studentDao;
//     指定异常为Exception,即包含其所有子异常
    @Transactional(rollbackFor = Exception.class)
    public void changeInfo(){
        studentDao.updateAgeById(20,1);
        System.out.println("-----------");
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        studentDao.updateNameById("test2",1);
    }
}

4.事务的隔离级别

事务可能会对数据进行修改,那么就会引发许多数据的问题,比如,脏读,幻读,不可重复读等问题。具体相关描述如下

  1. 脏读(Dirty Read): 脏读是指一个事务读取了另一个事务未提交的数据。假设有两个事务,事务A进行了修改但还未提交,事务B读取了事务A的修改后的数据,然后事务A回滚了。此时,事务B读取到的数据是无效或不一致的,这就是脏读。

  2. 幻读(Phantom Read): 幻读是指一个事务在同一个查询中多次进行读取,但是得到的结果集却不一致。假设事务A首先执行一个查询,返回了一些行,然后事务B插入了一些符合事务A查询条件的新行,接着事务A再次执行同样的查询,但结果集却发生了变化。这种情况下,事务A就发生了幻读,因为之前查询的结果集已经发生了变化。

  3. 不可重复读(Non-repeatable Read): 不可重复读是指在同一个事务中,多次读取同一条数据,但是得到的结果却不一致。假设事务A首先读取一条数据,然后事务B修改了该数据并提交,接着事务A再次读取同一条数据,发现结果与之前不同。这种情况下,事务A就遇到了不可重复读,因为同一条数据在事务执行期间发生了更改。

对此事务就有对应的隔离级别来避免相关问题的发生,但是注意,隔离级别越高,那么对应程序的性能将会越低。具体隔离级别如下

  • 读未提交(Read Uncommitted):事务可以读取未被提交的数据,容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全,一般不用。
  • 读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读问题,但可能引发不可重复读和幻读。
  • 可重复读(Repeatable Read):在一个事务中,相同的查询将返回相同的结果集,不管其他事务对数据做了什么修改。可以避免脏读和不可重复读,但仍有幻读的问题。
  • 串行化(Serializable):最高的隔离级别,完全禁止了并发,只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题,但效率较低,不适用于高并发场景。 不同的隔离级别适用于不同的场景,需要根据实际业务需求进行选择和调整。

事务属性名称:isolation

isolation的四个设置如下

隔离级别描述
READ UNCOMMITTED (读未提交)最低级别的隔离级别。它允许事务读取其他未提交事务所做的修改。可能出现脏读、幻读以及不可重复读。
READ COMMITTED (读已提交)事务只能读取已经提交的数据,不会读取未提交的数据。避免了脏读,但仍然可能出现幻读和不可重复读问题。
REPEATABLE READ (可重复读)事务在开始时读取一致的快照,并将该快照用于整个事务过程。确保了事务期间其他事务的插入操作不会影响到当前事务,但仍然可能出现幻读问题。
SERIALIZABLE (串行化)最高级别的隔离级别,保证事务串行执行,避免了脏读、幻读和不可重复读。所有并发事务按照顺序执行,但可能会牺牲一些并发性能。

注意:不同的数据库的默认事务隔离级别都是不同的,比如mysql就是第三级别。推荐设置第二级别即读已提交。

使用案例代码:

public class StudentService {

    @Autowired
    private StudentDao studentDao;

    //设置为读已提交隔离级别
    @Transactional(rollbackFor = Exception.class,
    isolation = Isolation.READ_COMMITTED)
    public void changeInfo(){
        studentDao.updateAgeById(20,1);
        System.out.println("-----------");
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        studentDao.updateNameById("test2",1);
    }
}

5. 事务的传播性

所谓的事务传播,即一个事务中调用了另一个事务,而对另一个事务是否加入原来事务还是独立出来单独的事务需要进行区分,则引入了事务的传播性来定义

属性:propagation

两个常用可选值:

传播属性描述
REQUIRED (默认值)如果当前存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务。这是大多数情况下的推荐选择,确保所有操作都在一个事务中执行。
REQUIRES_NEW创建一个新的事务,并挂起当前事务(如果存在)。新的事务独立于任何其他现有事务执行,并始终在自己的事务中操作。适用于需要完全独立的事务执行的场景。

 案例代码:

 //    设置为New 意味着算是一个独立的事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void changeName(){
        studentDao.updateNameById("黄小浓",2);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void changeAge(){
        studentDao.updateAgeById(55,2);
    }
    

这里具体解释一下是否独立意味着什么,如果独立了,那么如果在合并的事务中发生了异常,则事务将不会进行回滚,而在默认的Require的情况下,会先判断是否有其对应的父事务,如果没有才会进行创建事务。


本章总结

一、事务的种类

        1.认识编程式事务与声明式事务

二、Spring事务管理器

        1.认识几种常见的事务管理器

        2.熟悉并且会配置DataSourceTransactionManger事务管理器

三、事务注解使用

        1.熟悉@EnableTransactionManger、@Transaction注解

        2.熟悉事务注解的范围

四、事务属性

        1.熟悉事务的多种属性,比如只读(readonly)、超时时间(timeout)、指定异常、事务隔离级别、事务的传播

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

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

相关文章

Redis 7 第六讲 主从模式(replica)

🌹🌹🌹 此篇开始进入高级篇范围(❤艸`❤) 理论 即主从复制,master以写为主,Slave以读为主。当master数据变化的时候,自动将新的数据异步同步到其它slave数据库。 使用场景 读写分离 容灾备份数据备份水平扩容主从架构 演示案例 注:masterauth、replicaof主…

pytorch如何使用Focal Loss

Focal loss 是 文章 Focal Loss for Dense Object Detection 中提出对简单样本的进行decay的一种损失函数。是对标准的Cross Entropy Loss 的一种改进。 FL对于简单样本&#xff08;p比较大&#xff09;回应较小的loss。 如论文中的图1&#xff0c; 在p0.6时&#xff0c; 标准的…

openGauss学习笔记-57 openGauss 高级特性-并行查询

文章目录 openGauss学习笔记-57 openGauss 高级特性-并行查询57.1 适用场景与限制57.2 资源对SMP性能的影响57.3 其他因素对SMP性能的影响57.4 配置步骤 openGauss学习笔记-57 openGauss 高级特性-并行查询 openGauss的SMP并行技术是一种利用计算机多核CPU架构来实现多线程并行…

使用Vue3和Vite升级你的Vue2+Webpack项目

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

十一、做高并发内存池项目过程中遇到的bug以及调试bug的方法和心得

十一、做高并发内存池项目过程中遇到的bug以及调试bug的方法和心得 第一个bug是内存问题&#xff0c;程序直接崩溃&#xff0c;问题出现在&#xff1a;GetOneSpan函数中的切分span的时候结尾的span1的next没有置空。 第二个bug是还小内存块给span的时候找不到小内存所属的spa…

深入理解 JVM 之——Java 内存区域与溢出异常

更好的阅读体验 \huge{\color{red}{更好的阅读体验}} 更好的阅读体验 本篇为深入理解 Java 虚拟机第二章内容&#xff0c;推荐在学习前先掌握基础的 Linux 操作、编译原理、计算机组成原理等计算机基础以及扎实的 C/C 功底。 该系列的 GitHub 仓库&#xff1a;https://github…

LVS 实现四层负载均衡项目实战--DR模式(直接路由Direct Routing)

一、原理 负载均衡器和RS都使用同一个IP对外服务&#xff61;但只有DB对ARP请求进行响应,所有RS对本身这个IP的ARP请求保持静默&#xff61;也就是说,网关会把对这个服务IP的请求全部定向给DB,而DB收到数据包后根据调度算法,找出对应的RS,把目的MAC地址改为RS的MAC&#xff08…

MacOS 为指定应用添加指定权限(浏览器无法使用摄像头、麦克风终极解决方案)

起因&#xff1a;需要浏览器在线做一些测评&#xff0c;但我的 Chrome 没有摄像头/麦克风权限&#xff0c;并且在设置中是没有手动添加按钮的。 我尝试了重装软件&#xff0c;更新系统&#xff08;上面的 13.5 就是这么来的&#xff0c;我本来都半年懒得更新系统了&#xff09…

Tomcat安装及环境配置

一、首先确认自己是否已经安装JDK WinR打开运行&#xff0c;输入cmd回车&#xff0c;在DOS窗口中输入java 出现这些说明已经安装了&#xff0c;然后就是查看自己的版本 然后输入java -version 可以看到版本是1.8的 如果没有配置java环境变量&#xff0c;打开系统设置&#…

Linux安装JenkinsCLI

项目简介安装目录 mkdir -p /opt/jenkinscli && cd /opt/jenkinscli JenkinsCLI下载 wget http://<your-jenkins-server>/jnlpJars/jenkins-cli.jar # <your-jenkins-server> 替换为你的 Jenkins 服务器地址 JenkinsCLI授权 Dashboard-->Configure Glob…

渣土车识别监测 渣土车未盖篷布识别抓拍算法

渣土车识别监测 渣土车未盖篷布识别抓拍算法通过yolov7深度学习训练模型框架&#xff0c;渣土车识别监测 渣土车未盖篷布识别抓拍算法在指定区域内实时监测渣土车的进出状况以及对渣土车未盖篷布违规的抓拍和预警。YOLOv7 的策略是使用组卷积来扩展计算块的通道和基数。研究者将…

交叉导轨具有那些方面的优势?

交叉导轨和直线导轨这两种导轨经常被拿出来对比&#xff0c;从结构上来看&#xff0c;交叉导轨是分体结构&#xff0c;组装起来相对于直线导轨比较繁琐&#xff1b;从功能上来看&#xff0c;交叉导轨适合于短行程&#xff0c;高频率、高精度的场合。直线导轨可以做到6000mm单支…

Paimon+StarRocks 湖仓一体数据分析方案

摘要&#xff1a;本文整理自阿里云高级开发工程师曾庆栋&#xff08;曦乐&#xff09;在 Streaming Lakehouse Meetup 的分享。内容主要分为四个部分&#xff1a; 传统数据仓库分析实现方案简介PaimonStarRocks 构建湖仓一体数据分析实现方案StarRocks 与 Paimon 结合的使用方式…

从零开始,掌握C语言中的数据类型

数据类型 1. 前言2. 预备知识2.1 打印整数2.2 计算机中的单位 3. C语言有哪些数据类型呢&#xff1f;3.1 内置类型和自定义类型 4. 每种类型的大小是多少&#xff1f;5. 为什么有这么多数据类型呢&#xff1f;6. 这么多类型应该如何使用呢&#xff1f;6.1 一个小知识 1. 前言 …

Redis功能实战篇之Session共享

1.使用redis共享session来实现用户登录以及token刷新 当用户请求我们的nginx服务器&#xff0c;nginx基于七层模型走的事HTTP协议&#xff0c;可以实现基于Lua直接绕开tomcat访问redis&#xff0c;也可以作为静态资源服务器&#xff0c;轻松扛下上万并发&#xff0c; 负载均衡…

【VR】Network Manager HUD

&#x1f4a6;本专栏是我关于VR开发的笔记 &#x1f236;本篇是——Network Manager HUD Network Manager HUD组件 简介基础知识 简介 网络管理器 HUD是一种快速启动工具&#xff0c;可帮助您立即开始构建多人游戏&#xff0c;而无需首先构建用于游戏创建/连接/加入的用户界面…

云原生Kubernetes:二进制部署K8S单Master架构(一)

目录 一、理论 1.K8S单Master架构 2. etcd 集群 3.flannel网络 4.K8S单Master架构环境部署 5.部署 etcd 集群 6.部署 docker 引擎 7.flannel网络配置 二、实验 1.二进制部署K8S单Master架构 2. 环境部署 3.部署 etcd 集群 4.部署 docker 引擎 5.flannel网络配置…

Ramp 有点意思的题目

粗一看都不知道这个要干什么&#xff0c;这 B 装得不错。 IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoKJycnCktlZXAgdXMgb3V0IG9mIGdvb2dsZSBzZWFyY2ggcmVzdWx0cy4uCgokIG9kIC1kIC9kZXYvdXJhbmRvbSB8IGhlYWQKMDAwMDAwMCAgICAgNjAyMTUgICAyODc3OCAgIDI5MjI3ICAgMjg1NDggICA2MjY4NiAgIDQ1MT…

浏览器端vscode docker搭建(附带python环境)

dockerfile from centos:7 #安装python环境 run yum -y install wget openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel zlib-devel libffi-devel gcc make run wget https://www.python.org/ftp/python/3.9.0/Python-3.9.0.tgz run tar -xvf Python-3.9.…

六、编辑器vim编辑器的使用

1、编辑器 (1)编辑器就是一款软件。 (2)作用就是用来编辑文件&#xff0c;譬如编辑文字、编写代码。 (3)Windows中常用的编辑器&#xff0c;有自带的有记事本(notepad)&#xff0c;比较好用的notepad、VSCode等。 (4)Linux中常用的编辑器&#xff0c;自带的最古老的vi&…