解决方法A调用方法B的事务控制问题
关于方法A调用方法B的事务控制问题

实测,不管是上图还是下图,得到的结论都是一致的,那就是:
前提是同一个类里的方法调用,controller层类调用service的B方法,事务自然会生效的
a.异常发生后,被调用方法(B)是否添加事务控制,对于事务的回滚是否并不产生影响
b.调用B的方法,添加了事务控制才能实现异常事务回滚,不管被调用方法B是否有事务控制
c.不管嵌套调用了多少个方法,只要最顶层方法(没被同一个类中其他方法调用的且调用了同一个类里其他方法的方法),有事务控制,那么不管是哪个被调用的方法异常,整个调用的业务数据都回滚,不管被调用的方法是否有添加了事务的控制

其实,最好的办法是根据自己实际调用的情况,模拟测试一下就知道了。
同一个类的不同方法,A方法没有@Transactional,B方法有@Transactional,A调用B方法,事务不起作用
问题
同一个类的不同方法,A方法没有@Transactional,B方法有@Transactional,A调用B方法,事务不起作用
原理解析
spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。
此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会启动transaction。
然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction,我们看到的现象就是@Transactional注解无效。
//接口
interface Service {
void A();
void B();
}
//目标类,实现接口
class ServiceImpl implements Service {
//no annotation here
@Override
public void A() {
this.B();
}
@Transactional
@Override
public void B() {
System.out.println("execute doNeedTx in ServiceImpl");
}
}
//代理类,也要实现相同的接口
class ProxyByJdkDynamic implements Service {
//包含目标对象
private Service target;
public ProxyByJdkDynamic(Service target) {
this.target = target;
}
//目标类中此方法带注解,进行特殊处理
@Override
public void B() {
//开启事务
System.out.println("-> create Tx here in Proxy");
//调用目标对象的方法,该方法已在事务中了
target.B();
//提交事务
System.out.println("<- commit Tx here in Proxy");
}
//目标类中此方法没有注解,只做简单的调用
@Override
public void A() {
//直接调用目标对象方法
target.A();
}
}那回到一开始的问题,我们调用的方法A不带注解,因此代理类不开事务,而是直接调用目标对象的方法。
当进入目标对象的方法后,执行的上下文已经变成目标对象本身了,因为目标对象的代码是我们自己写的,和事务没有半毛钱关系,此时你再调用带注解的方法,照样没有事务,只是一个普通的方法调用而已。
简单来说,内部调用本类方法,不会再走代理了,所以B的事务不起作用
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
Spring Web MVC框架学习之配置Spring Web MVC
这一篇文章讲的是Spring Web MVC各部分的配置方法,包括Java代码配置和XML文件配置以及MVC命名空间的使用方法。2017-03-03
SpringBoot项目多数据源及mybatis 驼峰失效的问题解决方法
这篇文章主要介绍了SpringBoot项目多数据源及mybatis 驼峰失效的问题解决方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2022-07-07
浅谈MyBatisPlus中LocalDateTime引发的一些问题和解决办法
MyBatisPlus进行数据库操作时,我们经常会遇到处理日期时间类型的需求,本文主要介绍了浅谈MyBatisPlus中LocalDateTime引发的一些问题和解决办法,具有一定的参考价值,感兴趣的可以了解一下2024-07-07
Java LocalDateTime获取时间信息、格式化、转换为数字时间戳代码示例
其实我们在Java项目中对日期进行格式化,主要是利用一些日期格式化类,下面这篇文章主要给大家介绍了关于Java LocalDateTime获取时间信息、格式化、转换为数字时间戳的相关资料,需要的朋友可以参考下2023-11-11
MybatisPlus字段自动填充失效,填充值为null的解决方案
这篇文章主要介绍了MybatisPlus字段自动填充失效,填充值为null的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-01-01


最新评论