Spring-TX 事务

目录

一、事务的种类

二、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//JDBCTemplatepublic JdbcTemplate jdbcTemplate( ){JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource());return jdbcTemplate;}
//    设置TransactionManger事务管理接口@Beanpublic TransactionManager transactionManager(DataSource dataSource){
//        创建DataSourceTransaction对象DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
//        配置对应的数据源dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
}

三、事务注解使用

使用的注解

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

使用的范围:类或是方法

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

案例代码:

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

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

案例代码:

@Service
@Transactional
public class StudentService {@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate 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.rhkb.cn/news/115755.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vulnhub系列靶机---JIS-CTF-VulnUpload-CTF01靶机

文章目录 1、网卡配置2、信息收集主机发现端口扫描目录扫描 3、漏洞探测4、漏洞利用一句话木马蚁剑 GetShellSSH连接提权 JIS文档说明 JIS-CTF-VulnUpload-CTF01靶机下载地址 该靶机有5个flag 1、网卡配置 开启靶机&#xff0c;看见加载的进度条按shift&#xff0c;看到如下界…

Astro 3.0 闪亮登场,让你轻松构建更快速、更流畅的前端应用

网站前端开发的领域不断演进&#xff0c;随着Astro 3.0的发布&#xff0c;它正在迈出巨大的一步。Astro 3.0引入了突破性的功能和增强功能&#xff0c;承诺改变我们构建和体验网络应用程序的方式。在本文中&#xff0c;我们将探讨Astro 3.0的主要亮点以及如何赋予开发人员创建更…

直播平台源码弹性云托管技术:稳定直播与降低成本的利器

在当今的互联网时代&#xff0c;直播平台源码层出不穷&#xff0c;直播平台源码不仅可以让人们获取最新的资讯、查找资料等信息获取&#xff0c;还能让人们在其中观看短视频、直播、与其他人聊天等互动放松&#xff0c;直播平台源码的受欢迎与平台人数的增加使得人们在选择直播…

【juc】读写锁ReentrantReadWriteLock

目录 一、说明二、读读不互斥2.1 代码示例2.2 截图示例 三、读写互斥3.1 代码示例3.2 截图示例 四、写写互斥4.1 代码示例4.2 截图示例 五、注意事项5.2.1 代码示例5.2.2 截图示例 一、说明 1.当读操作远远高于写操作时&#xff0c;使用读写锁让读读可以并发&#xff0c;来提高…

关于linux openssl的自签证书认证与nginx配置

自签文档链接 重点注意这块&#xff0c;不能写一样的&#xff0c;要是一样的话登录界面锁会报不安全 域名这块跟最后发布的一致 nginx配置的话 server {listen 443 ssl; //ssl 说明为https 默认端口为443server_name www.skyys.com; //跟openssl设置的域名保持一致s…

ffmpeg把RTSP流分段录制成MP4,如果能把ffmpeg.exe改成ffmpeg.dll用,那音视频开发的难度直接就降一个维度啊

比如&#xff0c;原来我们要用ffmpeg录一段RTSP视频流转成MP4&#xff0c;我们有两种方案&#xff1a; 方案一&#xff1a;可以使用以下命令将rtsp流分段存储为mp4文件 ffmpeg -i rtsp://example.com/stream -vcodec copy -acodec aac -f segment -segment_time 3600 -reset_t…

CSS中如何隐藏元素但保留其占位空间(display:none vs visibility:hidden)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ display: none;⭐ visibility: hidden;⭐ 如何选择⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为…

QT DAY 2

window.cpp #include "window.h" #include<QDebug> #include<QIcon> Window::Window(QWidget *parent) //构造函数的定义: QWidget(parent) //显性调用父类的构造函数 {//this->resize(430,330);this->resize(QSize(800,600));// this…

Spring Cloud + Spring Boot 项目搭建结构层次示例讲解

Spring Cloud Spring Boot 项目搭建结构层次示例讲解 Spring Cloud 项目搭建结构层次示例Spring Cloud示例&#xff1a; Spring Boot 项目搭建结构层次讲解Spring Boot 项目通常按照一种常见的架构模式组织&#xff0c;可以分为以下几个主要层次&#xff1a;当构建一个 Spring…

【Android-Flutter】我的Flutter开发之旅

目录: 0、文档&#xff1a;1、在Windows上搭建Flutter开发环境&#xff08;1&#xff09;[使用中国镜像(❌详细看官方文档)](https://docs.flutter.dev/community/china)&#xff08;2&#xff09;[下载最新版Flutter SDK&#xff08;已包含Dart&#xff09;](https://docs.flu…

【rust/egui】(五)看看template的app.rs:SidePanel、CentralPanel以及heading

说在前面 rust新手&#xff0c;egui没啥找到啥教程&#xff0c;这里自己记录下学习过程环境&#xff1a;windows11 22H2rust版本&#xff1a;rustc 1.71.1egui版本&#xff1a;0.22.0eframe版本&#xff1a;0.22.0上一篇&#xff1a;这里 SidePanel 侧边栏&#xff0c;如下图 …

哈希表与有序表

哈希表与有序表 Set结构 key Map结构 key-value 哈希表 哈希表的时间复杂度都是常数项级别的&#xff0c;但常数较大 增删改查的时间都是常数级别的&#xff0c;与数据量无关 当哈希表存储的值是基础数据类型&#xff08;Integer - int&#xff09;&#xff0c;哈希表中内…

“MyBatis中的关联关系配置与多表查询“

目录 引言一、一对多关系配置二、一对一关系配置三、多对多关系配置总结 引言 在数据库应用开发中&#xff0c;经常会遇到需要查询多个表之间的关联关系的情况。MyBatis是一个流行的Java持久层框架&#xff0c;它提供了灵活的配置方式来处理多表查询中的一对多、一对一和多对多…

DVWA靶场搭建

目录 配置环境&#xff1a; 1、将下载好的压缩包放置php的WWW根目录下 2、改文件配置 3、查看mysql用户名和密码&#xff0c;将其修改值靶场配置文件中 4、完成后我们就可以在浏览器输入127.0.0.1/dvwa进入靶场 测试XSS注入&#xff1a; 配置环境&#xff1a; githhub下…

DEAP库文档教程一

DEAP是一个新的用于快速验证和测试新想法的演化计算框架。它致力于直接地构建算法和数据结构的简单化。它可以很好地应用在并行机制中。下面的文档将会展示许多关键概念以及构建你自己的演化算法时的一些特征。 第一步 1、总览(从这里开始) 2、安装 3、如何进入端口?(porting…

新型安卓恶意软件使用Protobuf协议窃取用户数据

近日有研究人员发现&#xff0c;MMRat新型安卓银行恶意软件利用protobuf 数据序列化这种罕见的通信方法入侵设备窃取数据。 趋势科技最早是在2023年6月底首次发现了MMRat&#xff0c;它主要针对东南亚用户&#xff0c;在VirusTotal等反病毒扫描服务中一直未被发现。 虽然研究…

浪潮云海护航省联社金融上云,“一云多芯”赋能数字农业

农村金融是现代金融体系的重要组成部分&#xff0c;是农业农村发展的重要支撑力量&#xff0c;而统管全省农商行及农信社的省级农村信用社联合社&#xff08;以下简称&#xff1a;省联社&#xff09;在我国金融系统中占据着举足轻重的地位。省联社通常采用“大平台小法人”的发…

每日一题(复制带随机指针的链表)

每日一题&#xff08;复制带随机指针的链表&#xff09; 138. 复制带随机指针的链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 由于每个链表还包含了一个random节点指向了链表中的随机节点&#xff0c;所以并不能直接照搬复制原链表。首先想到的暴力思路是复…

Docker构建Springboot项目,并发布测试

把SpringBoot项目打包成Docker镜像有两种方案&#xff1a; 全自动化&#xff1a;先打好docker镜像仓库&#xff0c;然后在项目的maven配置中配置好仓库的地址&#xff0c;在项目里配置好Dockerfile文件&#xff0c;这样可以直接在idea中打包好后自动上传到镜像仓库&#xff0c…

多因素认证与身份验证:分析不同类型的多因素认证方法,介绍如何在访问控制中使用身份验证以增强安全性

随着数字化时代的到来&#xff0c;信息安全问题变得愈发重要。在网络世界中&#xff0c;用户的身份往往是保护敏感数据和系统免受未经授权访问的第一道防线。单一的密码已经不再足够&#xff0c;多因素认证&#xff08;MFA&#xff09;应运而生&#xff0c;成为提升身份验证安全…