概述
项目开发中,经常遇到需要连接多个数据源的情况。
实现
直接给出代码。第一数据源配置:
import com.baomidou.mybatisplus.entity.GlobalConfiguration;
import com.baomidou.mybatisplus.mapper.LogicSqlInjector;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.aaa.cbd.platform.octopus.agg.dao.utils.DESDecryptutil;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@Slf4j
@Configuration
@Data
@Primary
@MapperScan(basePackages = "com.aaa.cbd.platform.octopus.agg.dao.mapper.primary",
sqlSessionFactoryRef = "sqlSessionFactoryBean")
public class PrimaryDataSourceConfig {
@Value("${datasource.primary.mapperLocations}")
private String[] thirdMapperLocations;
@Value("${datasource.primary.url}")
private String url;
@Value("${datasource.primary.username}")
private String userName;
@Value("${datasource.primary.password}")
private String password;
@Value("${datasource.primary.driverClassName}")
private String driverClassName;
@Value("${datasource.primary.hikari.autoCommit}")
private boolean autoCommit;
@Value("${datasource.primary.hikari.poolName}")
private String poolName;
@Value("${datasource.primary.hikari.minimumIdle}")
private int minIdle;
@Value("${datasource.primary.hikari.maximumPoolSize}")
private int maxPoolSize;
/**
* primary datasource 数据源属性、连接池属性
*/
@Bean(name = "dataSource", destroyMethod = "close")
public HikariDataSource dataSource() {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(driverClassName);
hikariConfig.setJdbcUrl(url);
hikariConfig.setUsername(userName);
// 此处可使用DES简单加密
hikariConfig.setPassword(password);
hikariConfig.setPoolName(poolName);
hikariConfig.setAutoCommit(autoCommit);
hikariConfig.addDataSourceProperty("cachePrepStmts", "true");
hikariConfig.addDataSourceProperty("prepStmtCacheSize", "250");
hikariConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
hikariConfig.addDataSourceProperty("useServerPrepStmts", "true");
hikariConfig.setMinimumIdle(minIdle);
hikariConfig.setMaximumPoolSize(maxPoolSize);
hikariConfig.setConnectionTestQuery("SELECT 1");
HikariDataSource dataSource = new HikariDataSource(hikariConfig);
log.info("======== third dataSource: {} =========", dataSource);
return dataSource;
}
/**
* sql会话工场
*/
@Bean(name = "sqlSessionFactoryBean")
public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("dataSource") HikariDataSource dataSource) {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(ResourceUtil.mapperLocations(thirdMapperLocations));
GlobalConfiguration config = new GlobalConfiguration();
config.setDbColumnUnderline(true);
config.setRefresh(false);
config.setSqlInjector(new LogicSqlInjector());
sqlSessionFactoryBean.setGlobalConfig(config);
return sqlSessionFactoryBean;
}
/**
* primary事务管理器
*/
@Bean(name = "dataSourceTransactionManager")
public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource") HikariDataSource dataSource) {
DataSourceTransactionManager manager = new DataSourceTransactionManager();
manager.setDataSource(dataSource);
return manager;
}
}
第三个数据源:
@Slf4j
@Configuration
@Data
@MapperScan(basePackages = "com.aaa.cbd.platform.octopus.agg.dao.mapper.third", sqlSessionFactoryRef = "thirdSqlSessionFactoryBean")
public class ThirdDataSourceConfig {
@Value("${datasource.third.mapperLocations}")
private String[] thirdMapperLocations;
/**
* 自定义数据源配置
*/
@Value("${datasource.third.url}")
private String url;
@Value("${datasource.third.username}")
private String userName;
@Value("${datasource.third.password}")
private String password;
@Value("${datasource.third.driverClassName}")
private String driverClassName;
@Value("${datasource.third.hikari.autoCommit}")
private boolean autoCommit;
@Value("${datasource.third.hikari.poolName}")
private String poolName;
@Value("${datasource.third.hikari.minimumIdle}")
private int minIdle;
@Value("${datasource.third.hikari.maximumPoolSize}")
private int maxPoolSize;
/**
* third datasource 数据源属性、连接池属性
*/
@Bean(name = "thirdDataSource", destroyMethod = "close")
public HikariDataSource secondaryDataSource() {
HikariConfig config = new HikariConfig();
config.setDriverClassName(driverClassName);
config.setJdbcUrl(url);
config.setUsername(userName);
config.setPassword(password);
config.setPoolName(poolName);
config.setAutoCommit(autoCommit);
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("useServerPrepStmts", "true");
config.setMinimumIdle(minIdle);
config.setMaximumPoolSize(maxPoolSize);
config.setConnectionTestQuery("SELECT 1");
HikariDataSource dataSource = new HikariDataSource(config);
log.info("======== supplier-log dataSource: {} =========", dataSource);
return dataSource;
}
/**
* third sql 会话工场
*/
@Bean(name = "thirdSqlSessionFactoryBean")
public MybatisSqlSessionFactoryBean secondarySqlSessionFactoryBean(@Qualifier("thirdDataSource") HikariDataSource dataSource) {
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMapperLocations(ResourceUtil.mapperLocations(thirdMapperLocations));
GlobalConfiguration config = new GlobalConfiguration();
config.setDbColumnUnderline(true);
config.setRefresh(false);
config.setSqlInjector(new LogicSqlInjector());
factoryBean.setGlobalConfig(config);
return factoryBean;
}
/**
* third 事务管理器
*/
@Bean(name = "thirdDataSourceTransactionManager")
public DataSourceTransactionManager secondaryDataSourceTransactionManager(@Qualifier("thirdDataSource") HikariDataSource dataSource) {
DataSourceTransactionManager manager = new DataSourceTransactionManager();
manager.setDataSource(dataSource);
return manager;
}
}
配置文件application.yml
:
spring:
# 排除datasource与mybatis自动装配
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
- org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
# multi datasource
datasource:
primary:
mapperLocations: classpath*:mybatis/primary/*Mapper.xml
driverClassName: com.mysql.cj.jdbc.Driver
hikari:
autoCommit: true
poolName: ds-primary-pool
minimumIdle: 10
maximumPoolSize: 10
third:
mapperLocations: classpath*:mybatis/third/*Mapper.xml
driverClassName: com.mysql.cj.jdbc.Driver
hikari:
autoCommit: true
poolName: ds-third-pool
minimumIdle: 10
maximumPoolSize: 50
数据源配置类扫描:
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
@Slf4j
public class ResourceUtil {
private ResourceUtil(){
throw new IllegalStateException("Utility class");
}
public static Resource[] mapperLocations(String[] mapperLocations) {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<Resource> resources = new ArrayList<>();
if (mapperLocations != null) {
for (String mapperLocation : mapperLocations) {
try {
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
}
catch (IOException e) {
// ignore
log.error("MapperLocations resolver failed, mapperLocations:{}, error:{}", mapperLocation, e);
}
}
}
return resources.toArray(new Resource[resources.size()]);
}
}