spring-tx笔记

编程式事务与声明式事务的理解

补充:什么是事务?

事务是一个重要概念,尤其在数据库管理系统中。事务是指一组操作。,这些操作要么全部成功执行,要么全部不执行,确保数据的一致性和完整性

编程式事务

编程式事务是指手动编写程序来管理事务,即通过编写代码的方式直接控制事务的提交和回滚。在 Java 中,通常使用事务管理器( Spring 中的 `PlatformTransactionManager`)来实现编程式事务

编程式事务的主要优点是灵活性高,可以按照自己的需求来控制事务的粒度、模式等等。但是,编写大量的事务控制代码容易出现问题,对代码的可读性和可维护性有一定影响

声明式事务(必须要有声明式事务的框架----------sprint-tx)

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

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

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

程序员只需要在配置文件即可(注解/xml)

指定那些方法需要添加事务以及事务的属性即可

区别:

- 编程式事务需要手动编写代码来管理事务

- 而声明式事务可以通过配置文件或注解来控制事务。

事务管理器

spring的事务管理会帮我们提供一个增强类(事务增强)有三个方法(开启事务(前置),提交事务(返回),事务回滚(异常));

但是持久层的框架有很多(不同框架事务的操作不同);所以提供了一个接口(事务管理器-----------具体提供事务方法的);在事务增强中通过  接口.方法()--------实现对应方法

spring提供了多种实现类(对应不同的数据库):

DataSoureceTransactionManager重写三个方法(jdbc,jdbcTampalte,myBatis框架)

我们使用的是那种数据库,就将对应的实现配置到ioc容器中;

然后在事务增强类上使用@Autowired(将实现类注入到增强类组件)

事务管理器

1. Spring声明式事务对应依赖

    - spring-tx: 包含声明式事务实现的基本规范(事务管理器规范接口和事务增强等等)

    - spring-jdbc: 包含DataSource方式事务管理器实现类DataSourceTransactionManager

    - spring-orm: 包含其他持久层框架的事务管理器实现类例如:Hibernate/Jpa等

2. Spring声明式事务对应事务管理器接口

   

我们现在要使用的事务管理器是org.springframework.jdbc.datasource.DataSourceTransactionManager,将来整合 JDBC方式、JdbcTemplate方式、Mybatis方式的事务实现!

    DataSourceTransactionManager类中的主要方法:

    - doBegin():开启事务

    - doSuspend():挂起事务

    - doResume():恢复挂起的事务

    - doCommit():提交事务

    - doRollback():回滚事务

基本实现

什么时候需要开启事务:

开启事务通常用于确保一组操作的原子性,一致性,隔离性,持久性

①多个操作需要原子性

当一组操作需要全部成功或者失败时

②数据一致性要求高

当多个操作需要保持数据的一致性时,事务可以确保在操作过程中数据不会处于不一致的状态

③并发控制

当多个用户或进程同时访问或修改同一数据时,事务可以通过 隔离级别来控制并访问

④错误恢复

当操作过程中可能发生错误时,事务可以确保在错误发生时回滚到操作前的状态,避免数据破损

⑥审计和日志记录

步骤:

1 选择对应的事务管理器实现加入到ioc容器

spring声明式事务给我们提供了各种管理器的实现

需要那种,就加入到ioc容器即可(在配置类中做此操作-------------类似于将第三方组件加入到ioc

2 只需要使用注解指定那些方法需要添加事务即可---------------声明式事务

3要在配置类开启事务注解的支持(@EnableTransactionManagement)

     * 给方法添加事务的操作

     *        1 选定我们需要的事务管理器的实现类,在配置类中创建该类的对象,使用注解的方法将该类添加到ioc

     *                         注意:该组件需要引入连接池的组件

     *        2 在配置类上加上 @EnableTransactionManagement 表示开启事务注解

     *        3 在我们想要添加事务的方法上加上 @Transactional那么该方法就有事务了

     *添加事务:

     *      @Transactional

     *      位置:方法/类上

     *      方法:当前方法有事务

     *      类上:类下所有方法都有事务

代码举例:

配置类

@Configuration
@ComponentScan("com.atguigu")
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement//开启事务注解的支持
public class JavaConfig {@Value("${atguigu.url}")private String url;@Value("${atguigu.driver}")private String driver;@Value("${atguigu.username}")private String username;@Value("${atguigu.password}")private String password;@Beanpublic DruidDataSource dataSource(){DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(url);dataSource.setDriverClassName(driver);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}@Beanpublic JdbcTemplate jdbcTemplate(DruidDataSource dataSource){JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}@Beanpublic TransactionManager transactionManager(DruidDataSource dataSource){/*内部要进行事务操作,是基于连接池的所以要将连接池给它*/DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}
}

Service类(要添加事务的方法在其中)

@Service
public class StudentService {@Autowiredprivate StudentDao studentDao;/***添加事务:*      @Transactional*      位置:方法/类上*      方法:当前方法有事务*      类上:类下所有方法都有事务*/@Transactionalpublic void changeInfo(){studentDao.updateAgeById(88,1);int i=1/0;System.out.println("-----------");studentDao.updateNameById("test2",1);}
}

测试代码:

@SpringJUnitConfig(JavaConfig.class)//指定那个是配置类

public class SpringTxTest {

    @Autowired

    private StudentService studentService;

    @Test

    public void test(){

        studentService.changeInfo();

    }

}

事务的几个属性设置 

只读模式

     * 只读模式

     *       只读模式可以提升查询事务的效率!推荐事务中只有查询代码是,使用只读模式

     *       默认: boolean readOnly() default false;

     *       解释: 一般情况下,都是通过类添加注解添加事务!

     *             类下所有方法全部都有事务!

     *             查询方法可以通过再次添加注解,设置只读模式提高效率!

 

1. 只读介绍(效率会提高,但是不允许做修改)

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

2   设置方式

// readOnly = true把当前事务设置为只读 默认是false!

@Transactional(readOnly = true)

事务超时时间设置

1. 需求

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

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

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

2  设置:

    /**

     * timeout设置事务超时时间,单位秒! 默认: -1 永不超时,不限制事务时间!

     */

    @Transactional(readOnly = false,timeout = 3)

 

     * 超时时间

     *        默认:永不超时  -1

     *        设置 timeout = 时间  (秒数)

     *        超过时间就会回滚事务和释放异常

     *    如果类上设置事务属性,设置了超时时间,而方法上有设置了事务属性,没有设置超时时间,那么时间限制会不会生效

     *    不会;因为:方法上的注解会将类上的注解覆盖

事务异常指定问题

     * 指定异常回滚和指定异常不回滚

     *         默认情况下,指定发生运行时异常事务才会回滚!

     *         我们可以指定Exception异常来控制所有异常都回滚!

     *             @Transactional(rollbackFor = Exception.class)

     *             noRollbackFor=回滚异常范围内,控制某个异常不回滚。

代码举例

在service类中

    @Transactional(rollbackFor = Exception.class,noRollbackFor = FileAlreadyExistsException.class)

    public void changeInfo(){

        studentDao.updateAgeById(88,1);

        int i=1/0;

        System.out.println("-----------");

        studentDao.updateNameById("test2",1);

    }

事务隔离级别

    数据库事务的隔离级别是指在多个事务并发执行时,数据库系统为了保证数据一致性所遵循的规定。常见的隔离级别包括:

    1. 读未提交(Read Uncommitted):事务可以读取未被提交的数据,容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全,一般不用。

    2. 读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读问题,但可能引发不可重复读和幻读。

    3. 可重复读(Repeatable Read):在一个事务中,相同的查询将返回相同的结果集,不管其他事务对数据做了什么修改。可以避免脏读和不可重复读,但仍有幻读的问题。------------------------------默认是可重复读(mysql中)

    4. 串行化(Serializable):最高的隔离级别,完全禁止了并发,只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题,但效率较低,不适用于高并发场景。

    不同的隔离级别适用于不同的场景,需要根据实际业务需求进行选择和调整。

 * 隔离级别设置

     *         推荐设置第二个隔离级别!

     *         isolation = Isolation.READ_COMMITTED(读已提交)

在service类中

    @Transactional(readOnly = true,isolation = Isolation.READ_COMMITTED)

    public void getStudentInfo(){

        //查询没有必要添加事务

        //获取学生信息 查询数据库 不修改

    }

 事务传播行为

在执行业务方法1时(事务1)要执行业务方法2(事务2)

那么:方法2的事务是否会加入方法1的事务呢?

这取决于事务传播的指定行为:事务之间的调用如何影响子事务

事务传播行为属性设置到子事务上

代码举例:

@Transactional

public void MethodA(){

    // ...

    MethodB();

    // ...

}

//在被调用的子方法中设置传播行为,代表如何处理调用的事务! 是加入,还是新事务等!

@Transactional(propagation = Propagation.REQUIRES_NEW)

public void MethodB(){

    // ...

}

1. propagation属性

    @Transactional 注解通过 propagation 属性设置事务的传播行为。它的默认值是:

Propagation propagation() default Propagation.REQUIRED;

    propagation 属性的可选值由 org.springframework.transaction.annotation.Propagation 枚举类提供:

  

* 声明两个独立修改数据库的事务业务方法

     * propagation = Propagation.REQUIRED 父方法有事务,我们就加入到父方法的事务!

     *                    最终是同一个事务!(推荐使用默认值)

     * propagation = Propagation.REQUIRES_NEW 

     *                    不管父方法中是否有事务,我都是独立的事务!

     *                    两个事务或者三个事务!

     */

代码举例

在TopService中(将两个事务合成了一个事务

    @Autowired

    private StudentService studentService;

    @Transactional

    public void  topService(){

        studentService.changeAge();

        studentService.changeName();

    }

在SudentService中

    @Transactional(propagation = Propagation.REQUIRED)

    public void changeAge(){

        studentDao.updateAgeById(998,1);

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)

    public void changeName(){- 

        studentDao.updateNameById("二狗子",1);

    }

**注意:**

  在同一个类中,对于@Transactional注解的方法调用,事务传播行为不会生效。这是因为Spring框架中使用代理模式实现了事务机制,在同一个类中的方法调用并不经过代理,而是通过对象的方法调用,因此@Transactional注解的设置不会被代理捕获,也就不会产生任何事务传播行为的效果。

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

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

相关文章

使用excel.EasyExcel实现导出有自定义样式模板的excel数据文件,粘贴即用!!!

客户要求导出的excel文件是有好看格式的,当然本文举例模板文件比较简单,内容丰富的模板可以自行设置,话不多说,第一步设置一个"好看"的excel文件模板 上面要注意的地方是{.变量名} ,这里的变量名对应的就是…

AutoGluon快速上手

我叫不三不四,很高兴见到大家,欢迎一起学习交流和进步 今天来讲一讲机器学习包 AutoGluon简介: AutoGluon 提供了多种模型来处理不同类型的数据和任务,是由 亚马逊 AWS 团队 开发的一款开源 AutoML 框架,旨在简化机器…

AI风向标《AI与视频制作全攻略:从入门到精通实战课程》

课程信息 AI风向标《AI与视频制作全攻略:从入门到精通实战课程》,夸克网盘和百度网盘课程。 课程介绍 《AI与视频制作全攻略:从入门到精通实战课程》是一套全面融合AI技术与视频制作的实战课程,旨在帮助创作者从基础软件使用到高级视频剪辑…

Docker学习笔记(十)搭建Docker私有仓库

一、环境配置 1、宿主机系统:macOS Sequoia(版本15.2) 2、虚拟机VMware Fusion版本:专业版 13.6.2 (24409261) 3、虚拟机系统:AlmaLinux-9-latest-x86_64-boot.iso 二、安装Harbor开源企业级Docker镜像 Harbor 是一个开源的企业级 Docker…

Linux中基本命令

目录 ls pwd cd touch mkdir rm cp mv cat less head tail find grep ls 其实大部分命令都是可执行的文件,但有一些命令比如Shell内置命令,它没有对应的独立可执行文件,而是由Shell直接解释执行的。 功能:显示当前目…

IDEA导入jar包后提示无法解析jar包中的类,比如无法解析符号 ‘log4j‘

IDEA导入jar包后提示无法解析jar包中的类 问题描述解决方法 问题描述 IDEA导入jar包的Maven坐标后,使用jar中的类比如log4j,仍然提示比如无法解析符号 log4j。 解决方法 在添加了依赖和配置文件后,确保刷新你的IDE项目和任何缓存&#xff…

字节跳动实习生主导开发强化学习算法,助力大语言模型性能突破

目录 禹棋赢的背景与成就 主要成就 DAPO算法的技术细节 算法优势 禹棋赢的研究历程 关键时间节点 字节跳动的“Top Seed人才计划” 计划特点 小编总结 在大模型时代,经验不再是唯一的衡量标准,好奇心、执行力和对新技术的敏锐洞察力成为推动技术…

Mysql表的简单操作

🏝️专栏:Mysql_猫咪-9527的博客-CSDN博客 🌅主页:猫咪-9527-CSDN博客 “欲穷千里目,更上一层楼。会当凌绝顶,一览众山小。” 目录 3.1 创建表 3.2 查看表结构 3.3 修改表 1. 添加字段 2. 修改字段 …

【一起学Rust | Tauri2.0框架】基于 Rust 与 Tauri 2.0 框架实现全局状态管理

前言 在现代应用程序开发中,状态管理是构建复杂且可维护应用的关键。随着应用程序规模的增长,组件之间共享和同步状态变得越来越具有挑战性。如果处理不当,状态管理可能会导致代码混乱、难以调试,并最终影响应用程序的性能和可扩…

大模型的微调技术(高效微调原理篇)

背景 公司有需求做农业方向的大模型应用以及Agent助手,那么适配农业数据就非常重要。但众所周知,大模型的全量微调对算力资源要求巨大,在现实的限制条件下基本“玩不起”,那么高效微调技术就非常必要。为了更好地对微调技术选型和…

Java 大视界 -- Java 大数据在智能家居设备联动与场景自动化中的应用(140)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

面试八股 —— Redis篇

重点:缓存 和 分布式锁 缓存(穿透,击穿,雪崩) 降级可作为系统的保底策略,适用于穿透,击穿,雪崩 1.缓存穿透 2.缓存击穿 3.缓存雪崩 缓存——双写一致性 1.强一致性业务&#xff08…

[网络安全] 滥用Azure内置Contributor角色横向移动至Azure VM

本文来源于团队的超辉老师,其系统分析了Azure RBAC角色模型及其在权限滥用场景下的攻击路径。通过利用AADInternals工具提升用户至Contributor角色,攻击者可在Azure VM中远程执行命令,创建后门账户,实现横向移动。文中详述了攻击步…

OO_Unit1

第一次作业 UML类图 代码复杂度分析 其中Expr中的toString方法认知复杂度比较高,主要源于多层条件嵌套和分散的字符串处理逻辑,重构时可重点关注这两部分的解耦。 代码量分析 1.”通用形式“ 我觉得我的设计的最大特点就是“通用形式”,具…

阿里云 AI 搜索产品荣获 Elastic Innovation Award 2024

阿里云AI搜索产品荣获Elastic Innovation Award 2024,该奖项于近日在新加坡ElasticON 2025的Elastic合作伙伴峰会上颁发,旨在表彰基于Elastic平台开发企业级生成式人工智能(GenAI)应用的顶尖合作伙伴,这些应用有效帮助…

网络原理之网络层、数据链路层

1. 网络层 1.1 IP协议 1.1.1 基本概念 主机: 配有IP地址,但是不进⾏路由控制的设备路由器: 即配有IP地址,⼜能进⾏路由控制节点: 主机和路由器的统称 1.1.2 协议头格式 说明: 4位版本号(version): 指定IP协议的版本,对于IPv4来说,就是4,对于IPv6来说,就是6 4位头…

炫酷的3D按钮效果实现 - CSS3高级特性应用

炫酷的3D按钮效果实现 - CSS3高级特性应用 这里写目录标题 炫酷的3D按钮效果实现 - CSS3高级特性应用项目介绍核心技术实现1. 基础结构设计2. 视觉效果实现2.1 背景渐变2.2 立体感营造 3. 交互动效设计3.1 悬停效果3.2 按压效果 技术要点分析1. 深度层次感2. 动画过渡3. 性能优…

Java定时任务的三重境界:从单机心跳到分布式协调

《Java定时任务的三重境界:从单机心跳到分布式协调》 本文将以生产级代码标准,揭秘Java定时任务从基础API到分布式调度的6种实现范式,深入剖析ScheduledThreadPoolExecutor与Quartz Scheduler的线程模型差异,并给出各方案的性能压…

鸿蒙Flutter开发故事:不,你不需要鸿蒙化

在华为牵头下,Flutter 鸿蒙化如火如荼进行,当第一次看到一份上百个插件的Excel 列表时,我也感到震惊,排名前 100 的插件赫然在列,这无疑是一次大规模的军团作战。 然后,参战团队鱼龙混杂,难免有…

PolyBench基准程序详解:编译器优化评测指标

PolyBench基准程序详解:编译器优化评测指标 PolyBench基本概念 PolyBench(Polyhedral Benchmark)是由UCLA(加州大学洛杉矶分校)的Louis-Nol Pouchet及其研究团队开发的基准测试套件,专门用于评估多面体编…