返回顶部
首页 > 资讯 > 精选 >spring中@Transactional的失效场景有哪些
  • 150
分享到

spring中@Transactional的失效场景有哪些

2023-06-22 08:06:16 150人浏览 八月长安
摘要

小编给大家分享一下spring中@Transactional的失效场景有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、失效场景集一:代理不生效Spring

小编给大家分享一下spring中@Transactional的失效场景有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

一、失效场景集一:代理不生效

Spring中对注解解析的尿性都是基于代理的,如果目标方法无法被Spring代理到,那么它将无法被Spring进行事务管理。

Spring生成代理的方式有两种:

  • 基于接口的jdk动态代理,要求目标代理类需要实现一个接口才能被代理

  • 基于实现目标类子类的CGLIB代理

Spring在2.0之前,目标类如果实现了接口,则使用JDK动态代理方式,否则通过CGLIB子类的方式生成代理。

而在2.0版本之后,如果不在配置文件中显示的指定spring.aop.proxy-tartget-class的值,默认情况下生成代理的方式为CGLIB,如下图

spring中@Transactional的失效场景有哪些

顺着代理的思路,我们来看看哪些情况会因为代理不生效导致事务管控失败。

(1)将注解标注在接口方法上

@Transactional是支持标注在方法与类上的。一旦标注在接口上,对应接口实现类的代理方式如果是CGLIB,将通过生成子类的方式生成目标类的代理,将无法解析到@Transactional,从而事务失效。

这种错误我们还是犯得比较少的,基本上我们都会将注解标注在接口的实现类方法上,官方也不推荐这种。

(2)被final、static关键字修饰的类或方法

CGLIB是通过生成目标类子类的方式生成代理类的,被final、static修饰后,无法继承父类与父类的方法。

(3)类方法内部调用

事务的管理是通过代理执行的方式生效的,如果是方法内部调用,将不会走代理逻辑,也就调用不到了。

例如

spring中@Transactional的失效场景有哪些

createUser中调用了内部方法createUser1,并且createUser1方法上设置了事务传播策略为:REQUIRES_NEW,但是因为是内部直接调用,createUser1不能不代理处理,无法进行事务管理。在createUser1方法抛出异常后就插入数据失败了。

但是这种操作在我们业务开发的过程中貌似还挺常见的,怎么样才能保证其成功呢?

方式1:新建一个Service,将方法迁移过去,有点麻瓜。

方式2:在当前类注入自己,调用createUser1时通过注入的userService调用

spring中@Transactional的失效场景有哪些

方式3:通过AopContext.currentProxy()获取代理对象

spring中@Transactional的失效场景有哪些

道理类似于方式2,就是为了通过代理来访问内部方法

(4)当前类没有被Spring管理

这个没什么好说的,都没有被Spring管理成为ioc容器中的一个bean,更别说被事务切面代理到了。

这种Bug看上去比较蠢,但没准真的有人犯错。

二、失效场景集二:框架或底层不支持的功能

这类失效场景主要聚焦在框架本身在解析@Transactional时的内部支持。如果使用的场景本身就是框架不支持的,那事务也是无法生效的。

(1)非public修饰的方法

我们在标有@Transactional的任意方法上打个断点,在idea内能看到事务切面点如下图所示

spring中@Transactional的失效场景有哪些

点击去这个方法,在开头有这么一个调用

spring中@Transactional的失效场景有哪些

继续进去

spring中@Transactional的失效场景有哪些

就能看到这么一句话了

spring中@Transactional的失效场景有哪些

不支持非public修饰的方法进行事务管理。

(2)多线程调用

跟上面一样的的操作,我们能够逐层进入到TransactionAspectSupport.prepareTransactionInfo方法。

注意看以下这段话

spring中@Transactional的失效场景有哪些

从这里我们得知,事务信息是跟线程绑定的。

因此在多线程环境下,事务的信息都是独立的,将会导致Spring在接管事务上出现差异。

这个场景我们要尤其注意!

给大家举个例子

主线程A调用线程B保存Id为1的数据,然后主线程A等待线程B执行完成再通过线程A查询id为1的数据。

这时你会发现在主线程A中无法查询到id为1的数据。因为这两个线程在不同的Spring事务中,本质上会导致它们在Mysql中存在不同的事务中。

Mysql中通过mvcC保证了线程在快照读时只读取小于当前事务号的数据,在线程B显然事务号是大于线程A的,因此查询不到数据。

(3)数据库本身不支持事务

比如mysql的Myisam存储引擎是不支持事务的,只有innodb存储引擎才支持。

这个问题出现的概率极其小,因为Mysql5之后默认情况下是使用innodb存储引擎了。

但如果配置错误或者是历史项目,发现事务怎么配都不生效的时候,记得看看存储引擎本身是否支持事务。

(4)未开启事务

这个也是一个比较麻瓜的问题,在SpringBoot项目中已经不存在了,已经有DataSourceTransactionManagerAutoConfiguration默认开启了事务管理。

但是在MVC项目中还需要在applicationContext.xml文件中,手动配置事务相关参数。如果忘了配置,事务肯定是不会生效的。

三、失效场景集三:错误使用@Transactional

注意啦注意啦,下面这几种都是高频会出现的Bug!

(1)错误的传播机制

Spring支持了7种传播机制,分别为:

spring中@Transactional的失效场景有哪些

上面不支持事务的传播机制为:PROPAGATION_SUPPORTS,PROPAGATION_NOT_SUPPORTED,PROPAGATION_NEVER。

如果配置了这三种传播方式的话,在发生异常的时候,事务是不会回滚的。

(2)rollbackFor属性设置错误

spring中@Transactional的失效场景有哪些

默认情况下事务仅回滚运行时异常和Error,不回滚受检异常(例如IOException)。

因此如果方法中抛出了IO异常,默认情况下事务也会回滚失败。

我们可以通过指定@Transactional(rollbackFor = Exception.class)的方式进行全异常捕获。

(3)异常被内部catch

UserService

spring中@Transactional的失效场景有哪些

UserService1

spring中@Transactional的失效场景有哪些

如上代码UserService调用了UserService1中的方法,并且捕获了UserService1中抛出的异常。

你将能看到控制台出现这样一个报错:

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

默认情况下标注了@Transactional注解的方法的事务传播机制是REQUIRED,它的特性是支持当前事务,也就说加入当前事务。我们在UserService中开始事务,然后再UserService1中抛出异常回滚UserService中的事务,将其标记为只读。

但是在UserSevice中我们捕获了异常,此时UserService上的事务认为正常提交事务。最后在提交时发现事务只读,已经被回滚,则抛出了上述异常。

因此这里如果需要对特定的异常进行捕获处理,记得再次将异常抛出,让最外层的事务感知到。

(4)嵌套事务

上面是我想同时回滚UserService与UserService1。但是也会有这种场景只想回滚UserService1中报错的数据库操作,不影响主逻辑UserService中的数据落库。

有两种方式可以实现上述逻辑:

直接在UserService1内的整个方法用try/catch包住

在UserService1使用Propagation.REQUIRES_NEW传播机制

spring中@Transactional的失效场景有哪些

四、总结

本文为大家分析@Transactional注解使用过程中失效的12种场景

spring中@Transactional的失效场景有哪些

最后,@Transactional注解虽香,但是复杂业务逻辑下,为了更好的管理事务与把控业务处理时事务的细粒度,我还是推荐大家使用编程式事务。

以上是“spring中@Transactional的失效场景有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: spring中@Transactional的失效场景有哪些

本文链接: https://lsjlt.com/news/303536.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • spring中@Transactional的失效场景有哪些
    小编给大家分享一下spring中@Transactional的失效场景有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、失效场景集一:代理不生效Spring...
    99+
    2023-06-22
  • spring中12种@Transactional的失效场景(小结)
    目录一、失效场景集一:代理不生效二、失效场景集二:框架或底层不支持的功能三、失效场景集三:错误使用@Transactional四、总结数据库事务是后端开发中不可缺少的一块知识点。Sp...
    99+
    2024-04-02
  • spring中事务失效的场景有哪些
    在Spring中,事务可能失效的场景包括:1. 方法未标记为事务:如果一个方法没有被@Transactional注解标记,那么Spr...
    99+
    2023-09-28
    spring
  • Spring事务的失效场景有哪些
    本篇内容主要讲解“Spring事务的失效场景有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring事务的失效场景有哪些”吧!1、Spring事务最终依赖的数据库的事务,如果用的是mys...
    99+
    2023-06-29
  • Spring事务失效的场景有哪些
    本篇内容主要讲解“Spring事务失效的场景有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring事务失效的场景有哪些”吧!概述Spring针对Java Transaction API...
    99+
    2023-07-05
  • Spring事务注解@Transactional失效的八种场景分析
    首先说一下最近自己遇到的一个坑: @Transactional service A(){ try{ insert(); serviceB.update(); }catch(){...
    99+
    2024-04-02
  • java事务失效的场景有哪些
    1. 并发更新:当多个线程同时对同一个数据进行更新操作时,可能会出现事务失效的情况。例如,线程A读取了一个数据,然后线程B修改了这个...
    99+
    2023-09-13
    java
  • MySQL索引失效的场景有哪些
    以下是一些导致MySQL索引失效的常见场景: 使用不符合最左前缀原则的查询条件:当查询条件中的列不是索引的最左前缀时,MySQL...
    99+
    2024-04-09
    MySQL
  • Mysql索引失效场景有哪些
    这篇文章主要介绍Mysql索引失效场景有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!数据库及索引准备创建表结构为了逐项验证索引的使用情况,我们先准备一张表t_user:CREA...
    99+
    2024-04-02
  • @Transactional 注解失效的原因有哪些
    @Transactional 注解失效的原因有哪些,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、事务事务管理在系统开发中是不可缺少的一...
    99+
    2024-04-02
  • 事务注解@Transactional失效的场景及解决办法
    本篇内容主要讲解“事务注解@Transactional失效的场景及解决办法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“事务注解@Transactional失效的场景及解决办法”吧!Transa...
    99+
    2023-06-15
  • Spring事务失效的场景分析
    这篇文章主要介绍“Spring事务失效的场景分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring事务失效的场景分析”文章能帮助大家解决问题。1)未被Spring管理使用Spring事务的前...
    99+
    2023-07-02
  • Spring事务失效场景的详细整理
    目录前言数据库引擎不支持事物方法不是 public 的自身调用问题不支持事物异常被吃掉异常类型错误总结前言 项目中用Spring的 @Transactional 注解控制事务,使用中...
    99+
    2024-04-02
  • Spring事务失效的场景梳理总结
    目录概述事务的传播类型事务隔离级别事务失效的场景概述 Spring针对Java Transaction API (JTA)、JDBC、Hibernate和Java Persisten...
    99+
    2023-02-23
    Spring事务失效场景 Spring事务失效原因
  • Spring事务失效的各种场景(13种)
    目录一、访问权限二、方法用final修饰三、方法内部调用四、没有被spring管理五、多线程调用六、设计的表不支持事务七、没有开启事务八、错误的事务传播九、自己捕获了异常十、手动抛出...
    99+
    2024-04-02
  • Spring详细讲解事务失效的场景
    目录1)未被Spring管理2)数据库引擎不支持事务3)事务方法没有被public修饰4)方法使用final修饰5)同一类中方法调用6)未开启事务7)多线程调用8)错误的传播行为9)...
    99+
    2024-04-02
  • Spring事务失效场景实例详解
    1、Spring事务最终依赖的数据库的事务,如果用的是mysql的话,执行引擎要是innodb;因为只有innoDB 支持事务。 2、Spring的事务是原理是aop,所以加事务所在...
    99+
    2024-04-02
  • 8个Spring事务失效场景详解
    目录前言Spring事务原理Spring事务失效场景1. 抛出检查异常2. 业务方法本身捕获了异常3. 同一类中的方法调用4. 方法使用 final 或 static关键字5. 方法...
    99+
    2022-12-20
    Spring事务失效场景 Spring事务失效
  • Python 在 Spring 框架中的应用场景有哪些?
    Python 和 Spring 框架都是在软件开发领域非常流行的工具,它们分别在不同的领域发挥着重要的作用。但是,Python 在 Spring 框架中的应用场景又有哪些呢?本文将为您详细介绍。 Spring Boot 中使用 Pytho...
    99+
    2023-09-04
    文件 关键字 spring
  • Spring框架中函数的使用场景有哪些?
    Spring框架是目前Java企业级开发中最为流行的框架之一,它提供了大量的功能和组件,可以帮助开发人员快速地构建高质量的应用程序。其中,函数是Spring框架中非常重要的一个组件,它可以方便地实现各种常用的功能,如数据访问、事务管理、AO...
    99+
    2023-08-19
    函数 bash spring
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作