In the case I experienced Since we built a system using different data sources and the same table definition, We will share the know-how at that time.
The driver uses "Oracle", but please modify it appropriately according to your environment.
application.yml
spring:
datasource:
#Data source A
alpha:
jdbc-url: jdbc:oracle:thin:@localhost:1521/XEPDB1
username: sample_a
password: sample_a
driverClassName: oracle.jdbc.OracleDriver
#Data source B
beta:
jdbc-url: jdbc:oracle:thin:@localhost:1521/XEPDB1
username: sample_b
password: sample_b
driverClassName: oracle.jdbc.OracleDriver
DataSourceConfig.java
package com.example;
@Configuration
@MapperScan(basePackages = { "com.example.mapper" }, sqlSessionTemplateRef = "sqlSessionTemplate") // ①
public class DataSourceConfig {
@Bean(name = "alphaDataSource")
@ConfigurationProperties(prefix = "spring.datasource.alpha")
public DataSource alphaDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "betaDataSource")
@ConfigurationProperties(prefix = "spring.datasource.beta")
public DataSource betaDataSource() {
return DataSourceBuilder.create().build();
}
@Bean("dynamicDataSource")
public DynamicRoutingDataSourceResolver dynamicDataSource(@Qualifier("alphaDataSource") DataSource alphaDataSource, @Qualifier("betaDataSource") DataSource betaDataSource) {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
targetDataSources.put(DataSourceType.ALPHA, alphaDataSource);
targetDataSources.put(DataSourceType.BETA, betaDataSource);
//Dynamic change of data source
DynamicRoutingDataSourceResolver resolver = new DynamicRoutingDataSourceResolver();
resolver.setTargetDataSources(targetDataSources);
resolver.setDefaultTargetDataSource(alphaDataSource);
return resolver;
}
@Bean
public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DynamicRoutingDataSourceResolver resolver) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
// ②
factoryBean.setDataSource(resolver);
factoryBean.setMapperLocations("Mapper XML path");
factoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return factoryBean.getObject();
}
// ...abridgement
}
①: Set an alias for the commonly used Mapper class (2): AutoConfigure is disabled for multi-data sources, so set it manually.
Define a partition value to determine the reference data source.
public enum DataSourceType {
ALPHA, BETA
}
The division value is held for each thread.
DataSourceContextHolder.java
public class DataSourceContextHolder {
private static ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<DataSourceType>();
public static void setDataSourceType(DataSourceType dataSourceType) {
contextHolder.set(dataSourceType);
}
public static DataSourceType getDataSourceType() {
return contextHolder.get();
}
public static void clear() {
contextHolder.remove();
}
}
Obtain the classification value for determining the reference data source. From the data source set in DataSourceConfig.dynamicDataSource with this indicator value Determine the data source to actually refer to.
DynamicRoutingDataSourceResolver.java
public class DynamicRoutingDataSourceResolver extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}
Let's set the DataSourceType via the DataSourceContextHolder. If you want to define it as cross-sectional processing, use AOP etc. to switch the data source.
DataSourceContextHolder.setDataSourceType(DataSourceType.ALPHA);
Recommended Posts