背景
随着业务的发展,在开发过程中,需要在一个工程里连接多个数据库,并兼容springBoot原本的与mybatis整合。
思路
看源码,过程大体是: 创建DataSource — 根据DataSource创建SqlSessionFactory — 根据SqlSessionFactory创建SqlSessionTemplate
这里,我将多个数据库作为多个数据源创建出来,并根据@MapperScan扫描多个包的机制,将不同的SqlSessionTemplate创建出来。
过程
创建第一个数据源:
@Configuration
@MapperScan(basePackages = "com.business.db1.mapper", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class Db1DataSourceConfig {
@Bean(name = "db1DataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource getDateSource() {
DataSource dataSource = DataSourceBuilder.create().build();
return dataSource;
}
@Bean(name = "db1SqlSessionFactory")
@Primary
public SqlSessionFactory memberSqlSessionFactory(@Qualifier("db1DataSource") DataSource datasource)throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com.business.db1/*.xml"));
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
return bean.getObject();
}
@Bean("db1SqlSessionTemplate")
@Primary
public SqlSessionTemplate memberSqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sessionFactory) {
return new SqlSessionTemplate(sessionFactory);
}
}
创建第二个数据源:
@Configuration
@MapperScan(basePackages = "com.business.db2.mapper", sqlSessionFactoryRef = "db2SqlSessionFactory")
public class Db2DataSourceConfig {
@Bean(name = "db2DataSource")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource getDateSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "db2SqlSessionFactory")
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("db2DataSource") DataSource datasource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com.business.db2/*.xml"));
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
return bean.getObject();
}
@Bean("db2SqlSessionTemplate")
public SqlSessionTemplate primarySqlSessionTemplate(
@Qualifier("db2SqlSessionFactory") SqlSessionFactory sessionFactory) {
return new SqlSessionTemplate(sessionFactory);
}
}
配置之后就可以。
新问题
我的db1数据源是用sharding做的分库分表,需要同时在一个工程里访问一个分库分表的数据源,一个普通的数据源。
使用后了解sharding配置后最终也是创建一个DataSource出来,交给spring托管;那我是不是将上面的db1里的数据源换成sharding的配置就可以了呢? 说干就干。
@Configuration
@MapperScan(basePackages = "com.business.db1.mapper", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class Db1DataSourceConfig {
@Bean(name = "db1DataSource")
@Primary
public DataSource getShardingDataSource(ShardingSliceProperties shardingSliceProperties) throws SQLException {
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
TableRuleConfiguration tableRuleConfiguration = new TableRuleConfiguration(shardingSliceProperties.getSliceTable(),
shardingSliceProperties.getSliceDatabase() + "_${0..15}." + shardingSliceProperties.getSliceTable() + "_${0..127}");
// 设置表规则
shardingRuleConfig.getTableRuleConfigs().add(tableRuleConfiguration);
// 设置分库规则
shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration(
shardingSliceProperties.getSliceDatabaseKey(), new OrderDatabaseAlgorithm()));
// 设置分表规则
shardingRuleConfig.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration(
shardingSliceProperties.getSliceTableKey(), new OrderTableAlgorithm()));
// 配置分库数据源
Map<String, DataSource> dataSourceMap = new HashMap<>();
for (int i = 0; i < 16; i++) {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setMinimumIdle(5);
hikariConfig.setMaximumPoolSize(25);
hikariConfig.setUsername(shardingSliceProperties.getUsername());
hikariConfig.setPassword(shardingSliceProperties.getPassword());
hikariConfig.setDriverClassName(shardingSliceProperties.getDriverClassName());
hikariConfig.setJdbcUrl(shardingSliceProperties.getJdbcUrl()+ "_" + i);
HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
dataSourceMap.put(shardingSliceProperties.getSliceDatabase() + "_" + i, hikariDataSource);
}
Properties props = new Properties();
// 设置显示sql
props.put(ShardingPropertiesConstant.SQL_SHOW.getKey(), String.valueOf(Boolean.TRUE));
// 配置默认数据源
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(shardingSliceProperties.getDriverClassName());
hikariConfig.setJdbcUrl(shardingSliceProperties.getJdbcUrl());
hikariConfig.setUsername(shardingSliceProperties.getUsername());
hikariConfig.setPassword(shardingSliceProperties.getPassword());
hikariConfig.setMaximumPoolSize(25);
hikariConfig.setMinimumIdle(5);
HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
dataSourceMap.put(shardingSliceProperties.getSliceDatabase(), hikariDataSource);
shardingRuleConfig.setDefaultDataSourceName(shardingSliceProperties.getSliceDatabase());
DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, props);
return dataSource;
}
@Bean(name = "db1SqlSessionFactory")
@Primary
public SqlSessionFactory memberSqlSessionFactory(@Qualifier("db1DataSource") DataSource datasource)throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com.business.db1/*.xml"));
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(configuration);
return bean.getObject();
}
@Bean("db1SqlSessionTemplate")
@Primary
public SqlSessionTemplate memberSqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sessionFactory) {
return new SqlSessionTemplate(sessionFactory);
}
}
启动报错,DataSouce NullPointException。 debug运行了一下,发现执行了org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration这个自动配置,在启动类exclude这个自动配置类搞定。
启动测试没问题。搞定。