@Transactional事务方法中包含多个同类事务方法,这些事务方法本身设置失效两种解决方案

导读:本篇文章讲解 @Transactional事务方法中包含多个同类事务方法,这些事务方法本身设置失效两种解决方案,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

@Transactional事务方法中包含多个同类事务方法,这些事务方法本身设置失效两种解决方案

问题背景

1 @Transactional同类方法调用,不同设置的@Transactional失效两种解决方案
2 伪代码举例说明问题

  • a,b,c三个方法在同一个类,为本方法调用
  • a,b,c三个方法的事务设置不同
  • 同类方法调用使 a,b 的Transactional事务设置失效,统一跟随 c 方法的事务设置,这并不是我们想要的结果
public class TransactionServiceImpl implements TransactionService {

    @Transactional(propagation = Propagation.MANDATORY)
    public void a(){

    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void b(){

    }

    @Transactional
    public void c(){
        //1. a,b,c三个方法在同一个类,为本方法调用
        //2. a,b,c三个方法的事务设置不同
        //3. 同类方法调用使a,b的Transactional事务设置失效,统一跟随 c 方法的事务设置,这并不是我们想要的结果
        a();
        b();
    }

}

解决方案一

1 因为事务注解是通过spring的IOC容器的控制反转实现的,直接调用本类方法,并没有使用spring的动态代理,所以可以更改为其他去调用其他类的方法,是动态代理生效

@Service
public class AbServiceImpl implements AbService {

    @Transactional(propagation = Propagation.MANDATORY)
    public void a(){

    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void b(){

    }

}
@Service
public class TransactionServiceImpl implements TransactionService {

    //从IOC容器中拿到代理对象,使动态代理生效
    @Autowired
    AbService abService; 

    @Transactional
    public void c(){
        //a,b,c三个方法在不同的类,使用动态代理的方式调用,这样可以实现三种Transactional事务设置各个都生效
        abService.a();
        abService.b();
    }

}

解决方案二

1 使用spring自带获取动态代理对象的依赖

        <!-- 引入aop -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2 在启动类使用@EnableAspectJAutoProxy(exposeProxy = true) 注解,开启aspect动态代理模式,对外暴露代理对象,可以代理当前对象,使@Asycn和@Transactional生效,所有动态代理使用aspectj创建,比JDK更多的好处是:没有开启接口也可以代理
如果不开启这个注解,默认使用JDK的动态代理

package com.lanran.transactional;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@EnableAspectJAutoProxy(exposeProxy = true)     //开启了aspect动态代理模式,对外暴露代理对象,可以代理当前对象,使@Asycn和@Transactional生效
@MapperScan("com.lanran.transactional.dao")
@SpringBootApplication
public class TransactionalApplication {

    public static void main(String[] args) {
        SpringApplication.run(TransactionalApplication.class, args);
    }

}

3 拿到代理对象调用方法

package com.lanran.transactional.service.impl;

import com.lanran.transactional.service.TransactionService;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author suolong
 * @Date 2022/7/21 11:21
 * @Version 2.0
 */
@Service
public class TransactionServiceImpl implements TransactionService {

    @Transactional(propagation = Propagation.MANDATORY)
    public void a() {

    }

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void b() {

    }

    @Transactional
    public void c() {
        //从上下文中拿到代理对象
        TransactionServiceImpl  transactionService = (TransactionServiceImpl) AopContext.currentProxy();
        transactionService.a();
        transactionService.b();
    }

}

总结

这个问题让我联想到@Async这个异步注解,原理也是一样的,同方法调用异步注解的方法,异步会失效,变成同步,只有调用其他类的@Async方法才生效

作为程序员第 209 篇文章,每次写一句歌词记录一下,看看人生有几首歌的时间,wahahaha …
@Transactional事务方法中包含多个同类事务方法,这些事务方法本身设置失效两种解决方案@Transactional事务方法中包含多个同类事务方法,这些事务方法本身设置失效两种解决方案@Transactional事务方法中包含多个同类事务方法,这些事务方法本身设置失效两种解决方案

Lyric: 随着右手旋律

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/110666.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!