【Spring面试】八、事务相关

文章目录

  • Q1、事务的四大特性是什么?
  • Q2、Spring支持的事务管理类型有哪些?Spring事务实现方式有哪些?
  • Q3、说一下Spring的事务传播行为
  • Q4、说一下Spring的事务隔离
  • Q5、Spring事务的实现原理
  • Q6、Spring事务传播行为的实现原理是什么?
  • Q7、Spring多线程事务,能否保证事务的一致性?
  • Q8、Spring事务失效的原因?

Q1、事务的四大特性是什么?

答案:

即ACID:

  • 原子性,Atomicity,即事务包含的所有操作要么同成功,要么同失败
  • 一致性,Cosistency,即事务必须使得数据库从一个一致性状态到两一个一致性状态。如用户A和用户B两者的钱加起来一共5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加来应该还得是5000,这就是事务的一致性
  • 隔离性,Isolation,多个事务并发时,之间要相互隔离,不能被其他事务干扰
  • 持久性,Durability,事务一旦提交,对数据库中数据的改变就是永久的,即使数据库故障也不会丢失提交事务的操作

Q2、Spring支持的事务管理类型有哪些?Spring事务实现方式有哪些?

答案: 支持的事务管理类型有两种

Spring支持两种类型的事务管理:

  • 编程式事务管理:灵活性高,但难维护
@Autowired
TransactionTemplate transactionTemplate ;

在这里插入图片描述

  • 声明式事务管理:业务代码和事务管理分离,只需用注解和xml配置来管理事务。以下为基于注解@Transactional

在这里插入图片描述

答案: 实现声明式事务的三种方式

  • 基于接口:Spring早期版本时用,更接近底层源码,有基于TransactionInterceptor的声明式事务,基于TransactionProxyFactoryBean的声明式事务
  • 基于<tx>和<aop>的xml声明式事务管理:和Spring AOP结合,利用切点表达式使得事务管理更加灵活
  • 基于@Transactional的全注解方式:在需要实施事务管理的方法或者类上加@Transactional注解,指定事务规则即可实现事务管理

Q3、说一下Spring的事务传播行为

答案:

两个事务方法之间的嵌套调用时,这个事务方法如何进行,即事务的传播特性。

@Transactional
public void trans(){sub();log();query();}@Transactional //SUPPORTS
public info query(){}@Transactional //REQUIRES_NEW
public void log(){}

在这里插入图片描述

以上面的query方法为例,其用SUPPORTS,即单独执行时不开启事务(就一个查询,当然不用开启),被有事务的外部方法调用时,则融入到这个外部方法的事务中,与他们同成功,同失败。(到大学了,和其余室友住一个屋子,还是你自己外面租一个新房子)

Q4、说一下Spring的事务隔离

答案:

事务隔离用来解决并发事务所产生的一些问题:

  • 脏读
  • 不可重复读
  • 幻影读

通过设置不同的隔离级别,可解决以上问题。

脏读:

在这里插入图片描述

事务2只是改了余额,但并未提交,事务1就把这个没提交的值读走了,如果以后事务2最终回滚,就出问题了。即一个事务读取了另一个事务中没有提交的数据,会在本事务中产生数据不一致的问题。

@Transactional(isolation = isolation.READ_COMMITTED)

设置事务隔离策略为读已提交,只读别的并发事务已提交的修改

不可重复读:

在这里插入图片描述
事务1先读后去处理其他事儿,然后期间事务2修改并commit,等事务1再读,则产生数据不一致的问题。

@Transactional(isolation = isolation.REPEATABLE_READ)

设置事务隔离策略为可重复读REPEATABLE_READ,确保事务1可以多次从一个字段中读到相同的值,即事务1执行期间禁止其他事务对这个字段进行更新(行锁)

幻影读:

不可重复读是针对一行数据,而幻影读则是针对整个表,比如两次读取,表中多出了一行数据:

在这里插入图片描述
一个事务所在的方法中,多次进行整表数据读取,结果不一样,产生数据不一致问题。

@Transactional(isolation = isolation.SERIALIZABLE)

需要设置事务级别为串行化SERIALIZABLE,确保事务1可以多次从一个表中读到相同的行数,事务1执行期间,禁止其他事务对这个表进行增删改,但这样性能十分低下(表锁)

最后,当不设置事务隔离级别时,将默认使用底层所选数据库自身的默认事务隔离级别。

SELECT @@tx_isolation;

Q5、Spring事务的实现原理

以JavaConfig的方式为例,使用是:

//启动事务,这样可以使用@Transactional注解
@EnableTransactionManagement

答案:

没有Spring之前,单靠JDBC来操作是这样的:


try {//...//将事务提交机制改为手动提交conn.setAutoCommit(false);//业务逻辑//在这里事务结束,手动提交数据conn.commit();}

Spring事务是把上面业务逻辑前后的事务开启与提交用AOP包了一下,即原理是:Spring事务底层是基于数据库事务和AOP机制。

  • 为使用了@Transactional注解的Bean创建一个动态代理对象(bean初始化后调用bean的后置处理器来创建动态代理)
  • 如果是事务方法(类上面、接口上面、方法上面、接口方法上面),则开启事务:
try{- 创建数据库连接- 修改数据库连接的autocommit属性为false,禁止此连接自动提交- 执行当前方法,方法中会执行数据库操作的业务SQL- 
}catch{- 若出现异常,且这个异常需要回滚,则回滚事务
}
  • 没有发生异常,则提交事务

Q6、Spring事务传播行为的实现原理是什么?

答案:

Spring的事务信息是存于ThreadLocal中的,所以一个线程永远只能有一个事务。对于被调用的事务方法,当:

  • 融入:当传播行为是融入外部事务,则拿到ThreadLocal中的Connection,共享一个数据库连接,来共同提交与回滚
  • 创建新事务:当传播行为是创建新的事务,则会把嵌套的新事务存入ThreadLocal,再将外部暂存起来,当嵌套事务提交或回滚后,再将暂存的外部事务信息恢复到ThreadLocal来提交或回滚

详细流程:

  • 外部:创建数据库连接Connection并存入ThreadLocal,修改数据库连接的autocommit属性为false
  • 外部:返回事务状态信息(TransactionInfo.newTransaction=true)
  • 外部:往下执行方法,中途发现内部调用了另一个事务方法
  • 内嵌:判断当前ThreadLoacl是否已有Connection,有即是内嵌事务,需要判断事务传播行为,到此分两种情况

情况一,当传播行为是融入

  • 不会创建connection,返回事务状态信息(TransactionInfo.newTransaction=false),即不是一个新事务
  • 内部被调用的事务方法开始执行相关SQL
  • 执行完后,判断TransactionInfo.newTransaction是否为true,此时是融入,这个值为false,不提交
  • 内部被调用的事务方法执行完成
  • 外部方法继续往下执行
  • 执行完后判断TransactionInfo.newTransaction是否为true,外部为true
  • 拿到ThreadLocal中的connection进行提交

情况二,当传播行为是创建新的事务

  • 把外层方法事务相关的事务信息(包括connection、隔离级别、是否只读…)暂存到TransactionInfo中,同时会把ThreadLocal中的事务信息置空
  • 创建新的connection,返回事务状态信息(TransactionInfo.newTransaction=true),即新事务,并放入ThreadLocal当中
  • 内部被调用的事务方法往下执行
  • 执行完后判断TransactionInfo.newTransaction是否为true⇒是⇒于是提交
  • 判断是否暂存了事务 ⇒ 是⇒ 再把上面暂存的外部方法的事务信息放回ThreadLocal中
  • 内部被调用的事务方法执行完成
  • 外部事务方法接着执行
  • 执行完后判断TransactionInfo.newTransaction是否为true,外部为true
  • 拿到ThreadLocal中的connection进行提交

Q7、Spring多线程事务,能否保证事务的一致性?

在这里插入图片描述
问题分析:两个事务方法A和B,在两个线程中,对应的事务能否同时提交或回滚?

答案:

Spring不支持,因为Spring事务信息存于ThreadLocal中的Connection,一个线程永远只能有一个事务,所以无法实现两个事务的一致性。可以通过编程式事务自己控制或者分布式事务来解决(二阶段提交的方式)。

Q8、Spring事务失效的原因?

在这里插入图片描述
Spring事务底层是基于数据库事务和AOP机制,因此,参考AOP失效,可以知道Spring事务失效的原因:

答案:

  • 方法的内部调用导致事务传播失效

在这里插入图片描述

  • 方法是private会失效,解决: 改成public
  • 目标类没有配置为Bean也会失效 解决: 配置为Bean,交给Spring管理
  • 自己捕获了异常 解决: 不要捕获处理
  • 使用cglib动态代理,但是@Transactional声明在接口上面

后面几种本质上是使用不当导致的失效。

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

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

相关文章

MySQL数据库查缺补漏——基础篇

MySQL数据库查缺补漏-基础篇 基础篇 net start mysql80[服务名] net stop mysql80 create database pshdhx default charset utf8mb4; 为什么不使用utf8&#xff1f;因为其字符占用三个字节&#xff0c;有四个字节的字符&#xff0c;所有需要设置为utf8mb4; 数值类型&…

SpringCloud Ribbon--负载均衡 原理及应用实例

&#x1f600;前言 本篇博文是关于SpringCloud Ribbon的基本介绍&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力…

​​​​MyBatis友人帐之基础入门

一、简介 1.1什么是MyBatis MyBatis 是一个开源的、轻量级的数据持久层框架&#xff0c;它可以简化 JDBC 的操作&#xff0c;让开发者只需要关注 SQL 语句本身&#xff0c;而不用处理加载驱动、创建连接、创建语句等繁琐的过程。 MyBatis 支持自定义 SQL、存储过程和高级映射&…

Kotlin中函数的基本用法以及函数类型

函数的基本用法 1、函数的基本格式 2、函数的缺省值 可以为函数设置指定的初始值&#xff0c;而不必要传入值 private fun fix(name: String,age: Int 2){println(name age) }fun main(args: Array<String>) {fix("张三") }输出结果为&#xff1a;张三2 …

论文笔记 DETR

detr 摘要和引言 2020论文facebook不需要proposal&#xff0c;不需要基于anchor的先验知识(比如预训练的模型)&#xff0c;也不需要NMS进行筛选&#xff0c;直接端到端不需要后处理利用transformer的全局建模能力&#xff0c;看成集合预测问题&#xff0c;不会输出很多冗余的…

浅谈DBT的一些不足之处

DBT的好处是显而易见的&#xff0c;它支持连接多达41种数据库。而且不需要你写DDL语句&#xff0c;只要写select语句&#xff0c;DBT会自动帮你推断schema结构&#xff0c;将数据写入到数据库中&#xff1a; 但是使用了一段时间之后&#xff0c;发现DBT也存在着如下这些不足之处…

竞赛 基于机器学习与大数据的糖尿病预测

文章目录 1 前言1 课题背景2 数据导入处理3 数据可视化分析4 特征选择4.1 通过相关性进行筛选4.2 多重共线性4.3 RFE&#xff08;递归特征消除法&#xff09;4.4 正则化 5 机器学习模型建立与评价5.1 评价方式的选择5.2 模型的建立与评价5.3 模型参数调优5.4 将调参过后的模型重…

JumpServer未授权访问漏洞 CVE-2023-42442

JumpServer未授权访问漏洞 CVE-2023-42442 一、漏洞描述二、漏洞影响三、网络测绘四、漏洞复现poc通过burp发送请求包小龙POC检测 五、修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接…

Redis代码实践总结

一、背景&#xff1a; redis从安装到实践&#xff0c;做一些具体的记录。 1.1 Redis和 RedisStack和Redis Enterprise redis简介 Redis 是一种开源&#xff08;BSD 许可&#xff09;内存中数据结构存储&#xff0c;用作数据库、缓存、消息代理和流引擎。 Redis 提供数据结构…

(JavaEE)(多线程案例)线程池 (简单介绍了工厂模式)(含经典面试题ThreadPoolExector构造方法)

线程诞生的意义&#xff0c;是因为进程的创建/销毁&#xff0c;太重了&#xff08;比较慢&#xff09;&#xff0c;虽然和进程比&#xff0c;线程更快了&#xff0c;但是如果进一步提高线程创建销毁的频率&#xff0c;线程的开销就不能忽视了。 这时候我们就要找一些其他的办法…

pte初步认识学习

我们的时间的确很少&#xff0c;但是我们每天都乐意将珍贵的时间浪费在大量毫无意义的事情上 目录 pte介绍 PTE口语评分规则 pte架构 计算机科学23 QS排名 《芭比》 pte介绍 PTE口语评分规则 有抑扬顿挫 对于连读 不能回读 native pte对于个别单词没有读好&#xff0c…

【探索C语言中VS调试技巧】:提高效率和准确性

文章目录 前言1. 什么是bug&#xff1f;2. 调试是什么&#xff1f;有多重要&#xff1f;2.1 调试是什么&#xff1f;2.2 调试的基本步骤2.3 Debug和Release的介绍 3. Windows环境调试介绍3.1 调试环境的准备3.2 学会快捷键3.3 调试的时候查看程序当前信息3.3.1 查看临时变量的值…

C语言生成随机数、C++11按分布生成随机数学习

C语言生成随机数 如果只要产生随机数而不需要设定范围的话&#xff0c;只要用rand()就可以&#xff1b;rand()会返回一随机数值, 范围在0至RAND_MAX 间&#xff1b;RAND_MAX定义在stdlib.h, 其值为2147483647&#xff1b; 如果想要获取在一定范围内的数的话&#xff0c;直接做…

【数据分享】2023年全国地级市点位数据(免费获取\shp格式\excel格式)

地级市点位数据是我们各项研究中经常使用到的数据&#xff0c;在之前的文章中我们分享过2022年度的地级市及以上城市的点位数据&#xff08;可查看之前的文章获悉详情&#xff09;。本次我们带来的是2023年度的全国范围的地级市及以上城市的点位数据&#xff0c;点位位置为市政…

大数据Flink(八十四):SQL语法的DML:窗口聚合

文章目录 SQL语法的DML:窗口聚合 一、滚动窗口(TUMBLE)

[激光原理与应用-68]:如何消除50Hz工频干扰和差分信号应对工频干扰

目录 一、什么工频干扰 1.1 什么工频干扰 1.2 工频干扰的幅度 1.3 工频干扰如何进入设备 1.4 工频干扰的负面影响 二、如何消除工频干扰 2.1 要消除工频干扰&#xff0c;可以考虑以下方法&#xff1a; 2.2 要具体消除工频干扰&#xff0c;可以采取以下措施 2.3 使用差…

React(react18)中组件通信04——redux入门

React&#xff08;react18&#xff09;中组件通信04——redux入门 1. 前言1.1 React中组件通信的其他方式1.2 介绍redux1.2.1 参考官网1.2.2 redux原理图1.2.3 redux基础介绍1.2.3.1 action1.2.3.2 store1.2.3.3 reducer 1.3 安装redux 2. redux入门例子3. redux入门例子——优…

Mybatis 中 SQL 注入攻击的 3 种方式

SQL注入漏洞作为WEB安全的最常见的漏洞之一&#xff0c;在java中随着预编译与各种ORM框架的使用&#xff0c;注入问题也越来越少。往往对Java Web应用的多个框架组合而心生畏惧&#xff0c;不知如何下手&#xff0c;希望通过Mybatis框架使用不当导致的SQL注入问题为例&#xff…

[Qt/C/C++]JSON和程序发布

文章摘于 爱编程的大丙 文章目录 1. JSON1.1 Json数组1.2 Json对象1.3 注意事项 2. Qt中JSON操作2.1 QJsonValue2.2 QJsonObject2.3 QJsonArray2.4 QJsonDocument2.5 举例2.5.1 写文件2.5.2 读文件 3. cjson库的使用3.1 cJSON结构体3.2 cJson API3.2.1 数据的封装3.2.2 Json对…

Kotlin File FileTreeWalk walkTopDown onEnter onLeave

Kotlin File FileTreeWalk walkTopDown onEnter onLeave Python遍历文件目录os.walk_for subfolder in subfolders: print(foldername/_zhangphil的博客-CSDN博客import osfor folderName, subfolders, filenames in os.walk(rD:\code\vs_code): print(当前文件夹: folderName…