参考的b站博主写的
配置文件:
spring:
datasource:
db1:
jdbc-url: jdbc:mysql://localhost:3306/interview_database?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 12345
driver-class-name: com.mysql.cj.jdbc.Driver
db2:
jdbc-url: jdbc:mysql://localhost:3306/cailu-family-manager?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 12345
driver-class-name: com.mysql.cj.jdbc.Driver
DataSourceChange.java 设定切换数据库的类,使用ThreadLocal
/**
* @author HFQ
* @version 1.0.0
* @ClassName DataSourceChange.java
* @Description 数据源切换
* @createTime 2024年07月03日 22:56:00
*/
public class DataSourceChange {
private static final ThreadLocal<String> contextHolder = new ThreadLocal();
// 设置默认数据库
static {
contextHolder.set("db1");
}
public static void setDB(String dbType){
contextHolder.set(dbType);
}
public static String getDB(){
return contextHolder.get();
}
}
DynamicDataSource 类设置数据源,继承AbstractRoutingDataSource类基于查找键将getConnection()调用路由到各种目标DataSource之一的抽象DataSource实现。后者通常(但不一定)是通过一些线程绑定的事务上下文来确定的。
/**
* @author HFQ
* @version 1.0.0
* @ClassName DynamicDataSource.java
* @Description 设置数据源
* @createTime 2024年07月03日 22:51:00
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceChange.getDB();
}
}
DataSourceConfig类多数据源配置
/**
* @author HFQ
* @version 1.0.0
* @ClassName DataSourceConfig.java
* @Description 多数据源配置
* @createTime 2024年07月03日 21:57:00
*/
@Configuration
public class DataSourceConfig {
/**
* @ConfigurationProperties用的反射来做这个功能
* @return
*/
@Bean(name = "db1")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource db1(){
return DataSourceBuilder.create().build();
}
@Bean(name = "db2")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource db2(){
return DataSourceBuilder.create().build();
}
@Bean(name = "dynamicDataSource")
@Primary
public DataSource dynamicDataSource(@Qualifier("db1")DataSource db1,@Qualifier("db2")DataSource db2){
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 设置默认数据源 这个代码有点重复了,因为我们在DataSourceChange类中已经设定了默认数据库
dynamicDataSource.setDefaultTargetDataSource(db1);
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("db1", db1);
objectObjectHashMap.put("db2", db2);
dynamicDataSource.setTargetDataSources(objectObjectHashMap);
return dynamicDataSource;
}
@Bean
public PlatformTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dynamicDataSource){
return new DataSourceTransactionManager(dynamicDataSource);
}
}
@ConfigurationProperties(prefix = “spring.datasource.db1”)
在Spring Boot中,@ConfigurationProperties注解用于将外部的配置属性(如application.yml或application.properties文件中的属性)映射到一个Java类的字段中。当你创建DataSourceBuilder并调用build方法时,Spring Boot会自动注入这些配置属性(使用的反射完成)。
测试一下
测试代码:
@Test
public void testDb1(){
// tagsMapper使用的是db1的连接,testMapper使用的是db2连接
ArrayList<String> strings = new ArrayList<>();
strings.add("女性");
strings.add("广州");
for (Integer tagsByName : tagsMapper.findTagsByNames(strings)) {
System.out.println(tagsByName);
}
// 切换到db2
DataSourceChange.setDB("db2");
List<Map<String, Object>> maps = testMapper.selectTest();
for (Map<String, Object> map : maps) {
System.out.println(map.get("account_name").toString());
}
}
然后, 既然是多数据源,那mapper.xml文件也需要分层
所以我的mapper文件夹是这样的
mapper-locations 使用逗号分隔
yml配置文件:
mybatis:
mapper-locations: classpath*:/mapper/db1/*.xml,classpath*:/mapper/db2/*.xml
执行结果: