1.AbstractRoutingDataSource
这个类提供的determineCurrentLookupKey()可以决定使用的是哪个数据源
2.自定义类继承AbstractRoutingDataSource,并在方法中决定数据源
public class DataSourceSelect {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
private static final String dataSourcePrefix="db";
public static void setDataSource(int key){
String s = dataSourcePrefix + key;
contextHolder.set(s);
}
public static String getDataSource(){
return contextHolder.get();
}
public static void clear(){
contextHolder.remove();
}
}
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
log.info("当前是数据是"+DataSourceSelect.getDataSource());
return DataSourceSelect.getDataSource();
}
}
3.application.yml中多数据源的配置
spring:
application:
name: test-demo
datasource:
#多数据源时需要写成driver-class-name
driver-class-name: com.mysql.cj.jdbc.Driver
#3个数据库配置
db1:
#多数据源时需要写成jdbc-url,而不能是url
jdbc-url: jdbc:mysql://10.250.200.102:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: 123
db2:
jdbc-url: jdbc:mysql://10.250.200.103:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: 123
db3:
jdbc-url: jdbc:mysql://10.250.200.104:3306/db3?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: 123
4.配置代码块
@SpringBootConfiguration
public class DataSourceConfig {
@Bean(name = "db1")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource dataSourceOne() {
return DataSourceBuilder.create().build();
}
@Bean(name = "db2")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource dataSourceTwo() {
return DataSourceBuilder.create().build();
}
@Bean(name = "db3")
@ConfigurationProperties(prefix = "spring.datasource.db3")
public DataSource dataSourceThree() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认数据源
dynamicDataSource.setDefaultTargetDataSource(dataSourceOne());
// 配置多数据源
Map<Object, Object> dsMap = new HashMap<>();
dsMap.put("db1", dataSourceOne());
dsMap.put("db2", dataSourceTwo());
dsMap.put("db3", dataSourceThree());
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
/**
* 配置多数据源后IOC中存在多个数据源了,事务管理器需要重新配置,不然器不知道选择哪个数据源
* 事务管理器此时管理的数据源将是动态数据源dynamicDataSource
* 配置@Transactional注解
* @return
*/
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dynamicDataSource());
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource());
//多数据源时需要在这里指定xml文件的路径
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
return sqlSessionFactoryBean;
}
}
5.简单的演示
try{
for(int n=1;n<=9;n++){
DataSourceSelect.setDataSource(n);
List<Map<String, Object>> list = visitingMapper.findVisiting();
if(list.size() == 0){
log.info("【任务】【结束】【当前需要下发的数据为0条】");
return;
}
log.info("【任务】【进行中】【当前需要下发的数据为{}条】",list.size());
DataSourceSelect.clear();
}
}catch (Exception e){
e.printStackTrace();
}
运行结果:
6.注意点
- application.yml配置文件里
url要写成jdbc-url
指定driver-class-name - 启动类上要去除DataSourceAutoConfiguration类
- 代码中指定xml文件的位置