SpringBoot动态切换数据源
导包
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
配置多个数据源
db:
# 数据库1
test:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: root
# 数据库2
test1:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: root
mybatis:
mapper-locations: classpath*:com/**/mapper/*.xml
数据库数据
- test数据库内容
- test2数据库内容
配置数据源类
test数据库
@Configuration
public class TestDataSourceBean {
@Value("${db.test.driver-class-name}")
private String testDriver;
@Value("${db.test.url}")
private String url;
@Value("${db.test.username}")
private String userName;
@Value("${db.test.password}")
private String password;
@Bean("testDataSource")
public DataSource testDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(testDriver);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
test2数据库
@Configuration
public class Test1DataSourceBean {
@Value("${db.test1.driver-class-name}")
private String testDriver;
@Value("${db.test1.url}")
private String url;
@Value("${db.test1.username}")
private String userName;
@Value("${db.test1.password}")
private String password;
@Bean("test1DataSource")
public DataSource test1DataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(testDriver);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
}
创建数据源切换类
public class DatabaseContextHolder {
private static final ThreadLocal<String> dataSource = new ThreadLocal<String>();
public static void setDataSource(String dataSource1){
dataSource.set(dataSource1);
}
public static String getDataSource(){
return dataSource.get();
}
}
创建动态切换数据源配置类
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDataSource();
}
}
分析
该类中的targetDataSource就是存储的数据源, 里面有个抽象方法determineCurrentLookupKey,重写该抽象方法,返回的值会当做key从targetDataSource
这个map中获对应的数据源,所以切换这个key就可以切换数据源了。
创建数据库数据库配置类
@Configuration
@MapperScan(basePackages = "com.wsl.mapper.test1",sqlSessionFactoryRef = "sqlSessionFactory")
public class MybatisConfig {
@Bean
@Primary
public DynamicDataSource dataSource(@Qualifier("test1DataSource")DataSource dataSource1,@Qualifier("testDataSource")DataSource dataSource2){
//将配置好的数据源放入到targetDataSource中
Map<Object,Object> dataSourceMap = new HashMap();
dataSourceMap.put("test1",dataSource1);
dataSourceMap.put("test",dataSource2);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(dataSourceMap);
//设置默认的数据源
dataSource.setDefaultTargetDataSource(dataSource2);
return dataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("test1DataSource")DataSource dataSource1,@Qualifier("testDataSource")DataSource dataSource2) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(this.dataSource(dataSource1,dataSource2));
return sqlSessionFactoryBean.getObject();
}
}
创建测试类
service
@Service
public class TestServerImpl extends ServiceImpl<UserMapper1,User> implements TestServer{
@Autowired
private UserMapper1 mapper1;
@Autowired
private DynamicDataSource dataSource;
@Override
public List<User> selectAll() {
List<User> users = new ArrayList<>();
User user = baseMapper.selectAll();
//修改数据源
DatabaseContextHolder.setDataSource("test1");
User user2 = baseMapper.selectAll();
users.add(user);
users.add(user2);
return users;
}
}
controller
@RestController
public class TestController {
@Autowired
private TestServer testServer;
@RequestMapping("test")
public List<User> all(){
return testServer.selectAll();
}
}
效果
从上可以看出,调用同一个mapper,但查询出来的结果是不同数据库的。