Spring声明式事务@Transactional的一些问题的测试及求证

1.Spring的声明式事务@Transactional问题

前提:有两个方法,a方法对a表做修改操作,b方法对b表做修改操作

a方法调用b方法,然后a方法报错,伪代码如下

public void a() {//数据库修改操作CompensateLogDO compensateLogDO = new CompensateLogDO();compensateLogDO.setId(IdWorker.getId());compensateLogDO.setCompensateLogType("123");compensateLogMapper.insert(compensateLogDO);fullCalcErrorService.b();int i = 1 / 0;
}public void b() {//数据库修改操作FullCalcErrorDO fullCalcErrorDO = new FullCalcErrorDO();fullCalcErrorDO.setId(IdWorker.getId());fullCalcErrorDO.setRetryCount(0);fullCalcErrorDO.setProcessFlag(0);fullCalcErrorMapper.insert(fullCalcErrorDO);
}

a方法调用b方法,然后b方法报错,伪代码如下

public void a() {//数据库修改操作CompensateLogDO compensateLogDO = new CompensateLogDO();compensateLogDO.setId(IdWorker.getId());compensateLogDO.setCompensateLogType("123");compensateLogMapper.insert(compensateLogDO);fullCalcErrorService.b();
}public void b() {//数据库修改操作FullCalcErrorDO fullCalcErrorDO = new FullCalcErrorDO();fullCalcErrorDO.setId(IdWorker.getId());fullCalcErrorDO.setRetryCount(0);fullCalcErrorDO.setProcessFlag(0);fullCalcErrorMapper.insert(fullCalcErrorDO);int i = 1 / 0;
}

直接上结果:

  • √:数据库插入成功
  • ×:数据库插入失败
    在这里插入图片描述

在 Spring Boot 中,默认情况下,对于单个数据库操作(即单个 SQL 语句的执行),是采用自动提交的方式。这意味着每次执行单个数据库操作后,都会立即将数据提交到数据库,不会等待其他操作或事务的完成。

2.@Transactional数据库连接问题

声明式事务管理建立在 AOP 之上的。其本质是通过 AOP 功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前启动一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

也就是方法上加了@Transactional,在调用方法时就会获取一个数据库连接,并占用连接到方法结束;而不加@Transactional,只有执行到数据库(读或写)操作时才会获取一个数据库连接,数据库操作执行完就会释放连接

测试验证:

1.在两个方法都不加在@Transactional注解测试,分别在com.zaxxer.hikari.pool.HikariPool#getConnection()org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection打上断点,执行到第一个数据库操作,进入断点,可以看到数据库连接为HikariProxyConnection@1230471455,释放断点,继续执行到第二个数据库操作,又会进入断点,可以看到数据库连接为HikariProxyConnection@1135602287,可以证明只有执行到数据库(读或写)操作时才会获取一个数据库连接,数据库操作执行完就会释放连接

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

2.在a方法上加@Transactional注解,b方法不加@Transactional注解,还是分别在com.zaxxer.hikari.pool.HikariPool#getConnection()org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin打上断点,方法一执行,就会获取数据库连接,这里是用代理获取的,可以看到数据库连接为HikariProxyConnection@1868392374,释放断点继续执行,可以发现后续数据库操作不会再获取连接,可以证明方法上加了@Transactional,在调用方法时就会获取一个数据库连接,并占用连接到方法结束

在这里插入图片描述

3.@Transactional(readOnly = true)问题

@Transactional(readOnly = true) 是Spring Framework中用来声明只读事务的注解。当一个方法被标记为@Transactional(readOnly = true)时,Spring将会确保在该方法的执行过程中,不会对数据库进行写操作,即只进行读操作。进行写操作会报错!!!

虽然@Transactional(readOnly = true)的主要目的是为了告诉Spring该方法只涉及读操作,但是它在底层仍然会占用一个数据库连接,这是因为Spring需要通过数据库连接来执行查询操作。然而,由于该方法只进行读取操作,Spring会尽可能地使用数据库的只读连接,从而减少对数据库的负担。

@Transactional(readOnly = true)主要的优势是在于告诉Spring该方法只进行读取操作,从而让Spring能够优化数据库连接的使用。它适用于那些纯粹的查询方法或者只读取数据而不涉及更新的业务逻辑。

什么时候使用@Transactional(readOnly = true)呢?

  • 纯读取操作: 如果某个方法完全是只读操作,不涉及数据库的写入(INSERT、UPDATE、DELETE),那么可以使用 @Transactional(readOnly = true) 来标记这个方法。这样Spring将会优化数据库连接的使用,使用只读连接,从而减少对数据库的负担。

  • 提高并发性能: 在高并发读取密集的场景下,通过将一些只读的查询操作标记为 @Transactional(readOnly = true) 可以提高并发性能。因为只读事务通常会使用数据库的共享锁(Shared Lock),不会阻塞其他只读事务,这样可以减少数据库的锁竞争,提高并发能力。

  • 避免意外修改: 使用 @Transactional(readOnly = true) 可以防止开发人员在只读方法中意外执行了写入操作。如果在只读事务中尝试执行写入操作,会抛出异常,从而避免数据的修改。

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

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

相关文章

《Linux从练气到飞升》No.07 Linux第一个小程序-进度条的实现

🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的…

尚品汇总结一:后台商品管理(面试专用)

项目模块: 后台管理模块 分类管理 平台属性管理 品牌管理 品牌与分类管理 SPU管理(销售属性) SKU管理(上下架) 商品详情 购物车 订单 支付 秒杀 登录 :账号密码、手机验证码、微信扫码 手机验…

Docker入门及安装

文章目录 1.Docker概述:1.什么是docker2.为什么使用docker3.docker优点4.docker资源网址 2.Docker安装1.卸载旧版本dorcker(非必要)2.设置Docker仓库安装docker引擎4.启动验证docker卸载docker 3.Docker底层原理1.docker的结构和基本概念2.docker为什么比虚拟机快 1.Docker概述…

【iOS安全】OpenSSH使用

安装OpenSSH 在 Cydia 中直接查找和安装 OpenSSH 使用OpenSSH http://orinchen.github.io/blog/2014/01/15/install-and-use-openssh-on-ios/ 保证PC和iPhone在同一网段下 查看iPhone的IP地址 ssh root10.168.xx.xx 口令默认是alpine 或者也可以使用XShell等集成终端

企业上云实施路线图

企业上云步骤主要分为规划、设计、实施、验证、运维五个阶段。https://articles.e-works.net.cn/cloud/article144684.htm

机器学习---概述(一)

文章目录 1.人工智能、机器学习、深度学习2.机器学习的工作流程2.1 获取数据集2.2 数据基本处理2.3 特征工程2.3.1 特征提取2.3.2 特征预处理2.3.3 特征降维 2.4 机器学习2.5 模型评估 3.机器学习的算法分类3.1 监督学习3.1.1 回归问题3.1.2 分类问题 3.2 无监督学习3.3 半监督…

【大数据】ELK最简入门案例(带你进入ELK世界)

文章目录 1. 前言2. 安装3. 启动ELK启动Elasticsearch启动Kibana启动Logstash 4. 测试ELK环境 本文通过最简单纯正的案例带你入门ELK世界。 1. 前言 ELK是Elasticsearch、Logstash、Kibana的缩写,如果对Elasticsearch、Logstash、Kibana不是很了解,可以…

SpringBoot使用@Autowired将实现类注入到List或者Map集合中

前言 最近看到RuoYi-Vue-Plus翻译功能 Translation的翻译模块配置类TranslationConfig,其中有一个注入TranslationInterface翻译接口实现类的写法让我感到很新颖,但这种写法在Spring 3.0版本以后就已经支持注入List和Map,平时都没有注意到这…

redis五种数据类型介绍

、string(字符串) 它师最基本的类型,可以理解为Memcached一模一样的类型,一个key对应一个value。 注意:一个键最大能存储 512MB。 特性:可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512…

【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域)

文章目录 一、继承的定义1.定义格式2.继承基类成员访问方式的变化 二、基类和派生类对象赋值转换三、继承的作用域1. 在继承体系中基类和派生类都有独立的作用域。2.子类和父类中有同名成员3.成员函数的隐藏4.注意在实际中在继承体系里面最好不要定义同名的成员。 四、派生类的…

Unity Shader编辑器工具类ShaderUtil 常用函数和用法

Unity Shader编辑器工具类ShaderUtil 常用函数和用法 Unity的Shader编辑器工具类ShaderUtil提供了一系列函数,用于编译、导入和管理着色器。本文将介绍ShaderUtil类中的常用函数和用法。 编译和导入函数 CompileShader 函数签名:public static bool C…

Apache Kafka Learning

目录 一、Kafka 1、Message Queue是什么? 2、Kafka 基础架构 3、Kafka安装 二、Maven项目测试 1、Topic API 2、生产者&消费者 一、Kafka Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式…