多数据源下,加上事务注解,会默认查主数据库解决

260 阅读2分钟

多数据源下,在serice加上@Transactional事务注解,会默认查主数据库,解决此问题,在mapper层加上对应的数据源注解,然后在service层也加上对应的数据源注解。即可解决多数据源情况下,加上事务默认查主数据库的情况。

原因:

spring的ioc 容器中默认都是原生对象,只有通过aop增强的对象才是代理对象。 配置了aop的类或者类中方法上有@Transactional注解的 @Transactional注解的原理是基于aop的

查看当前对象是否是代理对象的方法:AopUtils.isAopProxy(对象)

情况1:类没被aop增强,并且类中方法没有@Transactional注解

执行结果:false , 不是代理类。

// 类B
@Component
public class B {
    public void save(){
        System.out.println("保存");
    }
}

// 测试类
@Controller
public class A {

    @Autowired
    B b;

    @RequestMapping(value = "/getList",method = RequestMethod.POST)
    public void proxyClassTest(){
        // 结果是false 因为ioc容器默认情况创建的都是原生类
        boolean aopProxy = AopUtils.isAopProxy(b);// false
        System.out.println("proxyClassTest.................");
    }
}
情况2:类被aop增强,并且类中方法没有@Transactional注解

执行结果:true , 是代理类。

// 类B
@Component
public class B {
    public void save(){
        System.out.println("保存");
    }
}
// Aop配置
    @Pointcut("(execution(public void cn.a.controller.*.*(..))) ")
    public void pubLog(){}
//测试类
@Controller
public class A {

    @Autowired
    B b;

    @RequestMapping(value = "/getList",method = RequestMethod.POST)
    public void proxyClassTest(){
        boolean aopProxy = AopUtils.isAopProxy(b);// true
        System.out.println("proxyClassTest.................");
    }
}
情况3:B类被aop增强,C类没被aop增强,并且类中方法没有@Transactional注解

执行结果:类B的实例是代理类 ,类C的实例不是代理类(因为类B被aop增强而类C没被增强)。

// 类B
package cn.a.controller;
@Component
public class B {
    public void save(){
        System.out.println("保存");
    }
}
// 类C
package cn.a;
@Component
public class C {
    public void save(){
        System.out.println("保存");
    }
}
// aop类
    @Pointcut("(execution(public void cn.a.controller.*.*(..))) ")
    public void pubLog(){}

// 测试类
@Controller
public class A {

    @Autowired
    B b;
    @Autowired
    C c;

    @RequestMapping(value = "/getList",method = RequestMethod.POST)
    public void proxyClassTest(){
        boolean aopProxy = AopUtils.isAopProxy(b);// true
        boolean aopProxy1 = AopUtils.isAopProxy(c);// false
        System.out.println("proxyClassTest.................");
    }
}
情况4:类没被aop增强,但是类中方法有@Transactional注解

执行结果:true , 是代理类。

// 类B 方法有@Transactional注解
@Component
public class B {
    @Transactional
    public void save(){
        System.out.println("保存");
    }
}
// 测试类
@Controller
public class A {

    @Autowired
    B b;

    @RequestMapping(value = "/getList",method = RequestMethod.POST)
    public void proxyClassTest(){
        boolean aopProxy = AopUtils.isAopProxy(b);// true
        System.out.println("proxyClassTest.................");
    }
}

bean依赖注入后 ,如果发现需要aop, 就会把注入的对象,换成代理对象 事务的视线就是aop代理

@Transactional 加在service, 拿的就是service的aop代理对象,service层如果不加对应的数据源DS注解,就会默认拿主数据源的数据库连接来代理service对象,此时service层默认指向主数据库,事务自然就会变成主库的事务。如果加上DS数据源注解,那么service的代理对象就变成了指定的数据库链接代理对象,事务也会成为你指定的ds数据源。

(不加事务,拿的是原始对象,mapper层就会正常打到从库)