Mybatis+SpringBoot 多数据源配置
记录一下多数据源的配置
目录结构通常是在dal层
@Configuration
@EnableConfigurationProperties({MysqlDataSourceConfig.class})
@MapperScan(value = "com.example.mytest.dal.dao.test1", sqlSessionFactoryRef = "test1SqlSessionFactory")
@Slf4j
public class Test1DataSourceConfiguration {
@Autowired
private Test1DataSourceConfig test1DalConfig;
@Resource
private PerformanceInterceptorIron interceptor;
@Bean("test1DataSource")
public DataSource test1DataSource() {
HikariConfig cfg = new HikariConfig();
cfg.setAutoCommit(false);
cfg.setConnectionTimeout(mysqlDalConfig.getConnTimeout());
cfg.setJdbcUrl(mysqlDalConfig.getJdbcUrl());
cfg.setDriverClassName(mysqlDalConfig.getDriverClassName());
cfg.setUsername(mysqlDalConfig.getUsername());
cfg.setPassword(mysqlDalConfig.getPassword());
cfg.setMaximumPoolSize(mysqlDalConfig.getMaximumPoolSize());
cfg.setPoolName(mysqlDalConfig.getPoolName());
cfg.setMaxLifetime(mysqlDalConfig.getMaxLifeTime());
cfg.setIdleTimeout(mysqlDalConfig.getIdleTimeout());
cfg.addDataSourceProperty("characterEncoding", mysqlDalConfig.getCharacterEncoding());
cfg.addDataSourceProperty("useUnicode", mysqlDalConfig.getUseUnicode());
cfg.addDataSourceProperty("cachePrepStmts", mysqlDalConfig.getCachePrepStmts());
cfg.addDataSourceProperty("prepStmtCacheSize", mysqlDalConfig.getPrepStmtCacheSize());
cfg.addDataSourceProperty("useServerPrepStmts", mysqlDalConfig.getUseServerPrepStmts());
return new HikariDataSource(cfg);
}
// 指定主数据源
@Bean(name = "test1TransactionManager")
@Primary
public DataSourceTransactionManager tradeTransactionManager(@Qualifier("test1DataSource") DataSource
tradeDataSource) {
return new DataSourceTransactionManager(tradeDataSource);
}
@Bean(name = "test1SqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("test1DataSource") DataSource tradeDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(tradeDataSource);
Interceptor[] interceptors = {interceptor};
sessionFactory.setPlugins(interceptors);
VFS.addImplClass(SpringBootVFS.class);
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/test1/*.xml"));
return sessionFactory.getObject();
}
}
@Configuration
@EnableConfigurationProperties({MysqlDataSourceConfig.class})
@MapperScan(value = "com.example.mytest.dal.dao.test2", sqlSessionFactoryRef = "test2SqlSessionFactory")
@Slf4j
public class Test2DataSourceConfiguration {
@Autowired
private Test2DataSourceConfig test2DalConfig;
@Resource
private PerformanceInterceptorIron interceptor;
@Bean("test2DataSource")
public DataSource test2DataSource() {
HikariConfig cfg = new HikariConfig();
cfg.setAutoCommit(false);
cfg.setConnectionTimeout(mysqlDalConfig.getConnTimeout());
cfg.setJdbcUrl(mysqlDalConfig.getJdbcUrl());
cfg.setDriverClassName(mysqlDalConfig.getDriverClassName());
cfg.setUsername(mysqlDalConfig.getUsername());
cfg.setPassword(mysqlDalConfig.getPassword());
cfg.setMaximumPoolSize(mysqlDalConfig.getMaximumPoolSize());
cfg.setPoolName(mysqlDalConfig.getPoolName());
cfg.setMaxLifetime(mysqlDalConfig.getMaxLifeTime());
cfg.setIdleTimeout(mysqlDalConfig.getIdleTimeout());
cfg.addDataSourceProperty("characterEncoding", mysqlDalConfig.getCharacterEncoding());
cfg.addDataSourceProperty("useUnicode", mysqlDalConfig.getUseUnicode());
cfg.addDataSourceProperty("cachePrepStmts", mysqlDalConfig.getCachePrepStmts());
cfg.addDataSourceProperty("prepStmtCacheSize", mysqlDalConfig.getPrepStmtCacheSize());
cfg.addDataSourceProperty("useServerPrepStmts", mysqlDalConfig.getUseServerPrepStmts());
return new HikariDataSource(cfg);
}
// 指定主数据源
@Bean(name = "test2TransactionManager")
@Primary
public DataSourceTransactionManager tradeTransactionManager(@Qualifier("test2DataSource") DataSource
tradeDataSource) {
return new DataSourceTransactionManager(tradeDataSource);
}
@Bean(name = "test2SqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("test2DataSource") DataSource tradeDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(tradeDataSource);
Interceptor[] interceptors = {interceptor};
sessionFactory.setPlugins(interceptors);
VFS.addImplClass(SpringBootVFS.class);
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/test2/*.xml"));
return sessionFactory.getObject();
}
}
从配置文件中读取数据库连接信息
@Data
@ConfigurationProperties(prefix = "spring.datasource")
public class Test1DataSourceConfig {
private String driverClassName;
private String jdbcUrl;
private String username;
private String password;
private Integer maximumPoolSize;
private Long idleTimeout;
private Long connTimeout;
private String poolName;
private Integer maxLifeTime;
private Integer prepStmtCacheSize;
private Boolean useUnicode;
private Boolean cachePrepStmts;
private Boolean useServerPrepStmts;
private String characterEncoding;
}
```java
public enum DataSourceType {
TEST1("test1DataSource"),
TEST2("test2DataSource");
private String dataSourceName;
DataSourceType(String dataSourceName) {
this.dataSourceName = dataSourceName;
}
public String getDataSourceName() {
return dataSourceName;
}
}
定义切面 动态数据库路由切面
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DatabaseSource {
DataSourceType value();
}
@Slf4j
@Aspect
@Component
public class DataSourceAspect {
@Before(value = "@annotation(databaseSource)")
public void before(JoinPoint joinPoint, DatabaseSource databaseSource) {
DynamicDataSource.setDataSourceType(databaseSource.value());
}
}
动态切换数据源
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<>();
/**
* 获取当前线程的数据源类型
*/
@Override
protected Object determineCurrentLookupKey() {
return getDataSourceType();
}
public static String getDataSourceType() {
return contextHolder.get().getDataSourceName();
}
public static void setDataSourceType(DataSourceType dataSourceType) {
contextHolder.set(dataSourceType);
}
}