前一阵子在项目中遇到了一个mybatis配置多数据源的坑,调试源码后解决该问题,总的来说,还是对mybatis的熟悉度不够,故踩了这个坑。

场景:项目中需要多数据源进行读库

因公司项目不便演示,现用本人的一台阿里云服务器和本机mysql作为多数据源的配置,拿来演示:

配置如下:

server:
  port: 8081
  servlet:
    context-path: /
    application-display-name: movie
spring:
  application:
    name: movie
  datasource:
    master:
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: root
      jdbcUrl: 'jdbc:mysql://服务器的ip:3306/wuznuan?useUnicode=true&characterEncoding=utf8&autoReconnect=true'
    test:
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: root
      jdbcUrl: 'jdbc:mysql://192.168.100.117:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true'
mapper:
  mappers: tk.mybatis.mapper.common.Mapper
  identity: MYSQL
  not-empty: false
logging:
  level.org.choviwu.movie: debug

然后再配置 配置多数据源 file

主数据源连接工厂 file 从数据源连接工厂 file

项目结构大概为这样子: file

生成好mapper代码之后,开始进行启动项目

file

结果如下,发现查找的服务器上的表居然串了? file

没关系,我们来调试模式查看

方法1

找到MapperProxy类,我们来看看

file

public class MapperMethod {

  private final SqlCommand command;
  private final MethodSignature method;

  public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
  //获取sql 命令  也就是这一行报的错 ,进入代码
   this.command = new SqlCommand(config, mapperInterface, method);
    this.method = new MethodSignature(config, mapperInterface, method);
  }
}

打开SqlCommand类:

file

这是因为mybatis再查到mapper没有该方法得时候会做xml和dao所对应得数据源,并刷新数据源 调试之后可得结果

方法2:

更换包名: 调试MapperScannerRegistrar类,也就是mapperscan注解所引入得组件类 这个类就是再mapperscan扫描包下的所有beandefination信息,如果没有扫描到,则注册进去,如果扫描到,则直接continue

回想一下刚刚配置到mybatisconfig和testmybatisconfig, 前者扫描到的是org.choviwu.movie.mapper,后者则是org.choviwu.movie.mapper.test 很明显,当前者加载并定义好bean之后 后者则不会再加载(spring默认注册的是单例bean)

开始调试源码 中间的方法暂时不调试,自己可以去看看,这里第一个扫描到的mapper是9个,而这里我们也看到了test包下的dao接口了 file

而扫描到test包后则注册了0个类,这里是因为spring定义类的时候判断是否单例,单例类只被缓存一次 具体到方法可再下面截图: file

file

以上可以得出个结论,我们可以给dao分个包,单独扫描指定的包,即可达到目的 file