多种数据源的共同使用在日常开发中是很常见的,当然微服务中可能没那么常见,毕竟服务划分细致,数据源也就单独出去了。这里来看一下,在springboot中mybatis的多数据源实现(这里选择mysql为数据库)。
多数据源配置
mybatis和mysql在springboot中的引入这里就不在说了,不了解的可以参见springboot中mysql与mybatis的引入。
多数据源,即为配置多个数据源,首先引入数据域配置(同时引入mybatis配置):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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命名数据源的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| 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); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| 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
:
1 2 3 4 5 6 7 8 9
| @SpringBootApplication( exclude = {DataSourceAutoConfiguration.class}) public class SpringbootAcMysqlMulti2Application {
public static void main(String[] args) { SpringApplication.run(SpringbootAcMysqlMulti2Application.class, args); }
}
|
同样,手动配置数据源,mybatis的自动配置是可以被引入,但是不会生效。因为数据域手动配置,所以需要在配置中配置datasource的时候指定mybatis的属性配置信息。可以在上面的配置代码中看见,我们这里通过MybatisProperties方式加入的,因为mybatis的自动配置已经将信息注入到该类中,只需要利用其引入到自定义的datasource中即可:
1 2 3
| DefaultResourceLoader resourceLoader = new DefaultResourceLoader(); sqlSessionFactoryBean.setConfigLocation(resourceLoader.getResource(mybatisProperties.getConfigLocation())); sqlSessionFactoryBean.setMapperLocations(mybatisProperties.resolveMapperLocations());
|
案例代码
案例配置代码以及相应的演示代码地址如下:
https://github.com/lazycece/springboot-actual-combat/tree/master/springboot-ac-mysql/springboot-ac-mysql-multi2