环境依赖:
Spring Boot:1.5.9
JDK:1.8.0
MySQL:5.7.17
Mybatis:3.3.0
本文主要就mybatis的多数据源切换和动态数据源加载的实现原理做分享;对于mybatis的基础可自行百度。由于在开始学习的时候,发现网上有很多人把多数据源切换和动态数据源加载混为一谈,导致在实现动态加载的时候,所很苦恼。所以有必要在这里做以简要说明:
多数据源切换:指项目所需要不止一个数据库的连接信息,eg:同一数据库地址下的不同库或者压根连地址都不同。
动态加载:指所需要的数据所在的数据库信息在项目启动前并不知道,只有在项目运行后根据业务逻辑获取到对应的数据库信息,并在代码的运行过程中,向Spring Boot中添加一个或多个mybatis实例。
单一数据源的连接
顾名思义,在项目中,在项目中只需要配置一个数据库的信息即可,业务所需要的所有数据均在这一个数据库下;这种场景通常能够适用于绝大部分的实际需求,因此这种实现的原理再次不做赘述,如有需求可自行百度。具体实现可参考源码spring-boot-mybatis-demo。
多数据源切换
业务场景:需要分别获取所有的用户信息和学生信息;但是已知用户信息在mybatis_demo数据库中,学生信息在mybatis_demo2 数据库中。如下图所示:
数据库mybatis_demo内有个用户表:user_info,表结构如下:
数据库mybatis_demo2内有一个学生表:student_info,表结构如下:
配置文件信息如下:
在这里介绍一种最为简单的实现方案:多数据源 - 多实例。
在熟悉了单实例数据源的实现后,不难看出,在Spring Boot中,通过为该数据源DataSource初始化一个与之对应的SessionFactory,从而实现连接。因此在面对多数据源的时候,可以分别为每个数据源写一个mybatis的config类,使其每个DataSource都拥有一个只属于自己的SessionFactory,这样就可以根据各自的mapper映射目录找到对应的mybaits实例;
这种实现方法要求不同的mybatis实例的mapper映射目录不能相同
把一个配置类作下的Bean命名统一,并注入相应的Bean,从而可以保证每一个SessionFactory所对应的配置信息唯一;具体配置如下:
第一个数据源的配置
/**
* Created by YHYR on 2017-12-25
*/
@Configuration
@MapperScan(basePackages = "com.yhyr.mybatis.mapper.UserMapper", sqlSessionTemplateRef = "oneSqlSessionTemplate")
public class MybatisConfig {
@Bean(name = "oneDataSource")
@ConfigurationProperties(prefix = "spring.datasource.one")
@Primary
public DataSource customDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "oneSqlSessionFactory")
@Primary
public SqlSessionFactory customSqlSessionFactory(@Qualifier("oneDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
return bean.getObject();
}
@Bean(name = "oneTransactionManager")
@Primary
public DataSourceTransactionManager customTransactionManager(@Qualifier("oneDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "oneSqlSessionTemplate")
@Primary
public SqlSessionTemplate customSqlSessionTemplate(@Qualifier("oneSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
第二个数据源的配置:
/**
* Created by YHYR on 2017-12-25
*/
@Configuration
@MapperScan(basePackages = "com.yhyr.mybatis.mapper.StudentMapper", sqlSessionTemplateRef = "anotherSqlSessionTemplate")
public class MybatisConfig2 {
@Bean(name = "anotherDataSource")
@ConfigurationProperties(prefix = "spring.datasource.another")
public DataSource customDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "anotherSqlSessionFactory")
public SqlSessionFactory customSqlSessionFactory(@Qualifier("anotherDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
return bean.getObject();
}
@Bean(name = "anotherTransactionManager")
public DataSourceTransactionManager customTransactionManager(@Qualifier("anotherDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "anotherSqlSessionTemplate")
public SqlSessionTemplate customSqlSessionTemplate(@Qualifier("anotherSqlSessionFactory") SqlSessionFactory sqlSessionFactory) t