propagation为什么打不开

首页 > 实用技巧 > 作者:YD1662023-07-30 22:05:42

一、前言

emm,又又又踩坑啦。这次的需求主要是对逾期计算的需求任务进行优化,现有的计算任务运行时间太长了。简单描述下此次的问题:在项目中进行多个数据库执行操作时,我们期望的是将其整个封装成一个事务,要么全部成功,或者全部失败,然而在自测异常场景时发现,里面涉及的第一个数据状态更新成功了,但是后面的数据在插入出现异常,后面查询数据表发现,该数据的状态已经被更新成功啦

propagation为什么打不开,(1)

emmm,查看代码发现确实是使用了@Transactional注解没问啊。于是通过查询网上相关资料发现,在使用Spring中事务注解@transactional时会存在几种场景下该注解失效,即不能按照预期封装成一个事务操作,于是对该注解进行学习并对相关失效场景进行分析,整理文章如下;

二、@Transactional注解失效场景实例验证

1、@Transactional注解属性

属性

类型

描述

value

String

可选的限定描述符,指定使用的事务管理器

propagation

Enum:Propagation·

可选的事务传播行为设置

isolation

Enum:Isolation

可选的事务隔离级别设置

readOnly

boolean

读写或只读事务,默认读写

timeout

int

事务超时时间设置

rollbackFor

Class对象数组,必须继承自Throwable

导致事务回滚的异常类数组

rollbackForClassName

类名数组,必须继承自Throwable

导致事务回滚的异常类名字数组

noRollbackFor

Class对象数组,必须继承自Throwable

不会导致事务回滚的异常类数组

noRollbackForClassName

类名数组,必须继承自Throwable

不会导致事务回滚的异常类名字数组

2、 propagation属性

propagation代表事务的传播行为,默认值为Propagation.REQUIRED

属性

描述

Propagation.REQUIRED

若当前存在事务则加入该事务,若不存在则创建一个新事务(默认)

Propagation.SUPPORTS

若当前存在事务则加入该事务,若不存在则以非事务的方式继续进行

Propagation.MANDATORY

若当前存在事务则加入该事务,若不存在则抛出异常

Propagation.REQUIRES_NEW

重新创建一个新的事务,若当前存在事务则暂定当前事务

Propagation.NOT_SUPPORTED

以非事务的方式运行,若当前存在事务则暂定当前事务

Propagation.NEVER

以非事务的方式运行,若当前存在事务则抛出异常

Propagation.NESTED

与Propagation.REQUIRED效果一样

3、 @Transactional注解使用场景?

@Transactional注解可以作用在接口、类、类方法中。

当作用于类时,表示所有该类的public方法都配置相同的事务属性信息。

当作用于方法时,当类配置了@Transactional注解,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。

当作用于接口时,不推荐使用,因为在接口使用@Transactional并且配置了Spring AOP使用CGLib动态代理将会导致其失效。

4、 @Transactional注解失效场景?

@Transactional注解作用在非public修饰的方法上,会失效。

失效原因:在Spring AOP代理时,TransactionInterceptor(事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(CglibAopProxy的内部类)的Intercept方法或JDKDynamicAOPProxyinvoke方法会间接调用AbstractFallbackTransationAttributeSourcecomputeTransactionAttribute方法,获取@Transactional注解的事务配置信息。

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

此方法会检查目标方法的修饰符是否为public,非public作用域则不会获取@transactional的属性配置信息。其中protected、private修饰的方法上使用@Transactional注解,事务会失效但不会有任何报错。

@Transactional注解属性propagation设置错误导致注解失效

失效原因:配置错误, PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER三种事务传播方式不会发生回滚。

▪实例验证:写了一个demo进行测试。demo主要功能如下:执行两次数据库插入操作,并在扩展信息字段中添加备注;

propagation为什么打不开,(2)

▪运行结果如下,构造的单号不存在订单查询为空触发异常,观察数据库发现,第一次数据库插入操作已经执行成功,故而验证@Transactional注解失效

propagation为什么打不开,(3)

propagation为什么打不开,(4)

首页 123下一页

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.