多数据源下,在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层就会正常打到从库)