该文章收录专栏:

叶秋学长Spring系列专栏

叶秋学长主页:

新星计划第三季人工智能赛道TOP2;退役复学在校大学生,全栈JAVA领域创作者,目光所至,皆为华夏

目录

什么是事务?

23.Spring 事务的种类?

24.Spring 的事务隔离级别?

25.Spring 的事务传播机制?

26.声明式事务实现原理了解吗?

27.声明式事务在哪些情况下会失效?


什么是事务?

Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring 是无法提供事务功能的。Spring 只提供统一事务管理接口,具体实现都是由各数据库自己实现,数据库事务的提交和回滚是通过数据库自己的事务机制实现。接下来由叶秋学长带领你们学习Spring事务~

23.Spring 事务的种类?

Spring 支持编程式事务管理和声明式事务管理两种方式:

Spring事务分类

  1. 编程式事务

编程式事务管理使用 TransactionTemplate,需要显式执行事务。

  1. 声明式事务

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

  3. 优点是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过 @Transactional 注解的方式,便可以将事务规则应用到业务逻辑中,减少业务代码的污染。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

24.Spring 的事务隔离级别?

Spring的接口TransactionDefinition中定义了表示隔离级别的常量,当然其实主要还是对应数据库的事务隔离级别:

  1. ISOLATION_DEFAULT:使用后端数据库默认的隔离界别,MySQL 默认可重复读,Oracle 默认读已提交。

  2. ISOLATION_READ_UNCOMMITTED:读未提交

  3. ISOLATION_READ_COMMITTED:读已提交

  4. ISOLATION_REPEATABLE_READ:可重复读

  5. ISOLATION_SERIALIZABLE:串行化

25.Spring 的事务传播机制?

Spring 事务的传播机制说的是,当多个事务同时存在的时候——一般指的是多个事务方法相互调用时,Spring 如何处理这些事务的行为。

事务传播机制是使用简单的 ThreadLocal 实现的,所以,如果调用的方法是在新线程调用的,事务传播实际上是会失效的。

7种事务传播机制

Spring默认的事务传播行为是PROPAFATION_REQUIRED,它适合绝大多数情况,如果多个ServiceX#methodX()都工作在事务环境下(均被Spring事务增强),且程序中存在调用链Service1#method1()->Service2#method2()->Service3#method3(),那么这3个服务类的三个方法通过Spring的事务传播机制都工作在同一个事务中。

26.声明式事务实现原理了解吗?

就是通过AOP/动态代理。

  • 在Bean初始化阶段创建代理对象:Spring容器在初始化每个单例bean的时候,会遍历容器中的所有BeanPostProcessor实现类,并执行其postProcessAfterInitialization方法,在执行AbstractAutoProxyCreator类的postProcessAfterInitialization方法时会遍历容器中所有的切面,查找与当前实例化bean匹配的切面,这里会获取事务属性切面,查找@Transactional注解及其属性值,然后根据得到的切面创建一个代理对象,默认是使用JDK动态代理创建代理,如果目标类是接口,则使用JDK动态代理,否则使用Cglib。

  • 在执行目标方法时进行事务增强操作:当通过代理对象调用Bean方法的时候,会触发对应的AOP增强拦截器,声明式事务是一种环绕增强,对应接口为MethodInterceptor,事务增强对该接口的实现为TransactionInterceptor,类图如下:

    图片来源网易技术专栏

    事务拦截器TransactionInterceptorinvoke方法中,通过调用父类TransactionAspectSupportinvokeWithinTransaction方法进行事务处理,包括开启事务、事务提交、异常回滚。

27.声明式事务在哪些情况下会失效?

声明式事务的几种失效的情况

1、@Transactional 应用在非 public 修饰的方法上

如果Transactional注解应用在非 public 修饰的方法上,Transactional将会失效。

是因为在Spring AOP 代理时,TransactionInterceptor  (事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(CglibAopProxy  的内部类)的intercept方法 或  JdkDynamicAopProxy的invoke方法会间接调用AbstractFallbackTransactionAttributeSource的 computeTransactionAttribute方法,获取Transactional 注解的事务配置信息。

protected TransactionAttribute computeTransactionAttribute(Method method,Class<?> targetClass) {// Don't allow no-public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;
}

此方法会检查目标方法的修饰符是否为 public,不是 public则不会获取@Transactional 的属性配置信息。

2、@Transactional 注解属性 propagation 设置错误

  • TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

  • TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

3、@Transactional 注解属性 rollbackFor 设置错误

rollbackFor 可以指定能够触发事务回滚的异常类型。Spring默认抛出了未检查unchecked异常(继承自 RuntimeException的异常)或者 Error才回滚事务,其他异常不会触发回滚事务。

Spring默认支持的异常回滚

// 希望自定义的异常可以进行回滚
@Transactional(propagation= Propagation.REQUIRED,rollbackFor= MyException.class

若在目标方法中抛出的异常是 rollbackFor 指定的异常的子类,事务同样会回滚。

4、同一个类中方法调用,导致@Transactional失效

开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。

那为啥会出现这种情况?其实这还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。

 //@Transactional@GetMapping("/test")private Integer A() throws Exception {CityInfoDict cityInfoDict = new CityInfoDict();cityInfoDict.setCityName("2");/*** B 插入字段为 3的数据*/this.insertB();/*** A 插入字段为 2的数据*/int insert = cityInfoDictMapper.insert(cityInfoDict);return insert;}@Transactional()public Integer insertB() throws Exception {CityInfoDict cityInfoDict = new CityInfoDict();cityInfoDict.setCityName("3");cityInfoDict.setParentCityId(3);return cityInfoDictMapper.insert(cityInfoDict);}

这种情况是最常见的一种@Transactional注解失效场景

@Transactional
private Integer A() throws Exception {int insert = 0;try {CityInfoDict cityInfoDict = new CityInfoDict();cityInfoDict.setCityName("2");cityInfoDict.setParentCityId(2);/*** A 插入字段为 2的数据*/insert = cityInfoDictMapper.insert(cityInfoDict);/*** B 插入字段为 3的数据*/b.insertB();} catch (Exception e) {e.printStackTrace();}
}

如果B方法内部抛了异常,而A方法此时try catch了B方法的异常,那这个事务就不能正常回滚了,会抛出异常:

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

Spring系列九:Spring 事务相关推荐

  1. Spring系列--声明式事务管理

    Spring事务管理概述 Spring的事务管理简化了传统的事务管理流程,并且在一定程序上减少了开发者的工作量. 事务管理的核心接口 在Spring的所有JAR包中包含一个名为Spring-tx-5. ...

  2. Spring系列之Spring框架和SpringAOP集成过程分析(十)

    转载请注明出处:https://blog.csdn.net/zknxx/article/details/80724180 在开始这个系列之前大家先想一下我们是怎么在项目中使用SpringAOP的(这里 ...

  3. Spring系列 1.Spring概述及IOP

    Spring概述 简介 Spring : 春天 ->给软件行业带来了春天 2002年,Rod Jahnson首次推出了Spring框架雏形interface21框架. 2004年3月24日,Sp ...

  4. Spring系列之Spring常用注解总结

    参看博客:https://www.cnblogs.com/xiaoxi/p/5935009.html 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺 ...

  5. Spring系列之Spring Web MVC-20

    目录 Spring Web MVC DispatcherServlet 上下文层次结构 特殊Bean Web MVC 配置 程序配置 工作原理 异常 视图解析 配置 重定向 转发 内容协商 过滤器 F ...

  6. 【Spring 系列】Spring知识地图

    文章目录 Spring IOC 知道 会用 熟练 掌握 专家 Spring AOP 知道 会用 熟练 掌握 专家 Spring MVC 知道 会用 熟练 掌握 专家 Spring WebFlux 知道 ...

  7. Spring系列之Spring常用注解总结 原文:https://www.cnblogs.com/xiaoxi/p/5935009.html

    传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分开.xml文 ...

  8. Spring系列之一 Spring MVC

    摘要: 最近在看Spring的书,之前一直跟着项目做,虽然项目用到了Spring的很多功能,但是我很少有机会在工作的项目中去配置Spring.感觉只有理论是不够的,虽然只是用Spring的配置让人感觉 ...

  9. Spring系列(六) Spring Web MVC 应用构建分析

    DispatcherServlet DispatcherServlet 是Spring MVC的前端控制器名称, 用户的请求到达这里进行集中处理, 在Spring MVC中, 它的作用是为不同请求匹配 ...

  10. 【Spring系列】- Spring循环依赖

    Spring循环依赖

最新文章

  1. linux查看接口名,在linux下 怎么查看网络接口的名字? 网络接口的名字英文是什么呀?...
  2. common pool2 mysql_连接池Commons Pool2的使用
  3. android 的unregisterReceiver报错处理
  4. JUnit的各种断言
  5. mysql与jmeter环境变量配置_Java开发技术大杂烩(一)之Redis、Jmeter、MySQL的那些事...
  6. 云计算解决方案——电信行业
  7. 【实体对齐·HGCN】Jointly Learning Entity and Relation Representations for Entity Alignment
  8. Flink 作为现代数据仓库的统一引擎:Hive 集成生产就绪!
  9. 08-spring学习-annotation配置
  10. jsmin php,使用JSMin.php缩小Javascript
  11. atomic的安全性?
  12. java在线编译功能
  13. [转]24个英文电子书免费下载网站
  14. jcp jsr_JCP EC 2011年特别选举结果即将公布!
  15. vsCode自动保存与浏览器自动刷新
  16. AD21覆铜,包地,补泪滴,有图
  17. Spring-boot启动出现:“if you put a @ComponentScan in the default package by mistake” 错误。
  18. 软件测试之接口测试用例设计,全网独一份
  19. 光纤收发器怎么连?光纤收发器连接图解!
  20. OpenAI发布最强的人工智能对话模型——ChatGPT,火出AI圈,给我们体验和思考

热门文章

  1. 项目实训(十二)——FPS游戏枪械射击弹孔及子弹散射
  2. 第二章 SQL命令 ALTER TABLE(二)
  3. LIO-SAM论文翻译
  4. 表格OCR相关资源整理【ICDAR】【表格识别】【持续更新...】
  5. 一个30岁的程序员无比挣扎的故事,连躺平都是奢望
  6. CVPR2019资源汇总
  7. mysql 8.0 用户修改为简单密码
  8. vue2.5版本源代码编译报 Could not load ..\vue\src\core/config 错误的问题 npm run dev 编译报错...
  9. java实现多个excel表格数据整合成一个excel表格
  10. 世界观和方法论----写给学弟学妹的