Spring中同一类@Transactional修饰方法相互调用的坑

1.问题1的提出

class AServiceImpl{
	@AutoWide
	BService bService;
  @Transactional
    public void a() {
        bService.b();
        bService.c();
        int i =10/0;
    }
  }

class BServiceImpl{
    @Transactional(propagation = Propagation.REQUIRED,timeout = 2)
    public void b() {

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW,timeout = 2)
    public void c() {

    }
  }

bService.b()方法使用默认的传播行为REQUIRED,和a共用一个事务, int i =10/0;出现异常需要回滚,b会回滚。
bService.c()方法使用默认的传播行为REQUIRES_NEW,和a不共用一个事务, int i =10/0;出现异常需要回滚,b会回滚。

  • 结论:bService.b()回滚,bService.c()不回滚。

2.问题2的题提出

class AServiceImpl{
  @Transactional
        @Transactional
    public void a() {
        b();
        c();
    }

    @Transactional(propagation = Propagation.REQUIRED,timeout = 2)
    public void b() {
        System.out.println("b");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW,timeout = 2)
    public void c() {
        System.out.println("c");
    }

  }

的写法和下面的写法一模一样:

class AServiceImpl{

    @Transactional
    public void a() {
        System.out.println("b");
        System.out.println("c");
    }
  }

即b和c自己的事务失效,完全相当于拷贝代码到a方法中。如果我们想要的是各自拥有自己的自治的事务,该怎么办呢?为什么会出现这个问题?

2.1为什么为出现bc方法事务失效的问题?

原因:@Transactional 底层使用的是aop,使用的代理对象才能使用事务,本方法内部嗲用,绕过了代理对象,所以bc事务无效,a仍然有效(如果其类通过代理对象调用的话)。

2.2解决方案

1.先引入aspactj的依赖:

 	 	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
 在嗲用b,c方法之前通过切面重新获得此对象的代理AServiceImpl aService = AopContext.currentProxy();
 可以解决这个问题。
 代码如下:
 class AServiceImpl{

    @Transactional
    public void a() {
    	AServiceImpl aService = AopContext.currentProxy();
       aService.b();
       aService.c();
    }
    @Transactional(propagation = Propagation.REQUIRED,timeout = 2)
    public void b() {
        System.out.println("b");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW,timeout = 2)
    public void c() {
        System.out.println("c");
    }
  }

2.3其他的解决方案

另外在抽象出一层,做事务层,不要把相互调用的方法放到一类中

2.4错误的解决方案

这种会造成循环依赖,会爆炸:

@AutoWide
AServiceImpl AServiceImpl;
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值