多种数据源的共同使用在日常开发中是很常见的,当然微服务中可能没那么常见,毕竟服务划分细致,数据源也就单独出去了。这里来看一下,在springboot中mybatis的多数据源实现(这里选择mysql为数据库)。
多数据源配置
mybatis和mysql在springboot中的引入这里就不在说了,不了解的可以参见springboot中mysql与mybatis的引入。
多数据源,即为配置多个数据源,首先引入数据域配置(同时引入mybatis配置):
datasource:
master:
type: com.alibaba.druid.pool.DruidDataSource
jdbc-url: jdbc:mysql://127.0.0.1:3306/sbac_master?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: 1234
driver-class-name: com.mysql.cj.jdbc.Driver
log:
type: com.alibaba.druid.pool.DruidDataSource
jdbc-url: jdbc:mysql://127.0.0.1:3306/sbac_log?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: 1234
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
config-location: classpath:mybatis-config.xml
mapper-locations: classpath:com/lazycece/sbac/mysql/data/dao/*/mapper/*.xml
springboot中,可以通过@MapperScan
注解来实现多数据源中的数据源路由,可以选择使用注解的属性basePackages、basePackageClasses、annotationClass、markerInterface来标记mapper的所属数据源,注解的详情信息可自行参考源码。
这里使用包路径(basePackages,不适用其他属性表示该包下的所有mappe被包含)属性来示例配置两个数据源,当然也可以配置更多。下面给出以master和log命名数据源的配置:
package com.lazycece.sbac.mysql.multi2.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = {"com.lazycece.sbac.mysql.data.dao.master"},
sqlSessionFactoryRef = "masterSqlSessionFactory",
sqlSessionTemplateRef = "masterSqlSessionTemplate")
public class MasterDataSourceConfig {
@Resource
private MybatisProperties mybatisProperties;
@Primary
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
sqlSessionFactoryBean.setConfigLocation(resourceLoader.getResource(mybatisProperties.getConfigLocation()));
sqlSessionFactoryBean.setMapperLocations(mybatisProperties.resolveMapperLocations());
return sqlSessionFactoryBean.getObject();
}
@Primary
@Bean(name = "masterTransactionManager")
public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Primary
@Bean(name = "masterSqlSessionTemplate")
public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
package com.lazycece.sbac.mysql.multi2.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = {"com.lazycece.sbac.mysql.data.dao.log"},
sqlSessionFactoryRef = "logSqlSessionFactory",
sqlSessionTemplateRef = "logSqlSessionTemplate")
public class LogDataSourceConfig {
@Resource
private MybatisProperties mybatisProperties;
@Bean(name = "logDataSource")
@ConfigurationProperties(prefix = "datasource.log")
public DataSource logDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "logSqlSessionFactory")
public SqlSessionFactory logSqlSessionFactory(@Qualifier("logDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
sqlSessionFactoryBean.setConfigLocation(resourceLoader.getResource(mybatisProperties.getConfigLocation()));
sqlSessionFactoryBean.setMapperLocations(mybatisProperties.resolveMapperLocations());
return sqlSessionFactoryBean.getObject();
}
@Bean(name = "logTransactionManager")
public DataSourceTransactionManager logTransactionManager(@Qualifier("logDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "logSqlSessionTemplate")
public SqlSessionTemplate logSqlSessionTemplate(@Qualifier("logSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
由于手动配置数据源,故可以在主函数禁用掉自动数据源配置DataSourceAutoConfiguration
:
@SpringBootApplication(
exclude = {DataSourceAutoConfiguration.class})
public class SpringbootAcMysqlMulti2Application {
public static void main(String[] args) {
SpringApplication.run(SpringbootAcMysqlMulti2Application.class, args);
}
}
同样,手动配置数据源,mybatis的自动配置是可以被引入,但是不会生效。因为数据域手动配置,所以需要在配置中配置datasource的时候指定mybatis的属性配置信息。可以在上面的配置代码中看见,我们这里通过MybatisProperties方式加入的,因为mybatis的自动配置已经将信息注入到该类中,只需要利用其引入到自定义的datasource中即可:
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
sqlSessionFactoryBean.setConfigLocation(resourceLoader.getResource(mybatisProperties.getConfigLocation()));
sqlSessionFactoryBean.setMapperLocations(mybatisProperties.resolveMapperLocations());
案例代码
案例配置代码以及相应的演示代码地址如下: