【Spring】DynamicDataSourceHolder 动态数据源切换
一个开发系统需要用多个数据库怎么办呢?可不可以连接多个数据库?
当然可以!随意切换。
DynamicDataSourceHolder
通常是用于动态数据源切换的一个工具类,特别是在多数据源场景下使用。它通过 ThreadLocal
来保存当前线程的数据源标识,以便在同一线程中能够动态切换不同的数据源。
常见场景
在实际项目中,可能需要根据不同的业务需求在多个数据源之间进行切换。比如,读写分离(主从库)、多租户架构等。通过DynamicDataSourceHolder
可以方便地实现这一需求。
常见工具
有许多现有的动态数据源管理工具和框架,可以帮助简化多数据源配置和管理。以下是一些常用的工具和框架:
-
Spring Boot DataSource Routing with AbstractRoutingDataSource
Spring本身提供了AbstractRoutingDataSource
类,可以用于实现动态数据源路由。 -
Spring Cloud DataSource Routing
在Spring Cloud环境中,可以使用Spring Cloud提供的配置和工具实现动态数据源管理。 -
MyBatis Dynamic Datasource
MyBatis提供了一个动态数据源插件mybatis-spring,可以用于在MyBatis中实现动态数据源切换。 -
Dynamic Datasource for Spring Boot
动态数据源管理库dynamic-datasource-spring-boot-starter
,是一个简单易用的Spring Boot动态数据源启动器,支持多种数据源配置和切换。 -
Druid Dynamic Datasource
阿里巴巴的Druid数据源也支持动态数据源切换,可以通过配置Druid的相关属性实现。
下面详细介绍一下 Spring本身提供的 AbstractRoutingDataSource
、SpringBoot 动态数据启动器、以及现在常用的阿里巴巴的Druid数据源。
一、AbstractRoutingDataSource
1.1、 定义 DynamicDataSourceHolder
public class DynamicDataSourceHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 设置数据源
* @param dataSourceKey 数据源标识
*/
public static void setDataSource(String dataSourceKey) {
contextHolder.set(dataSourceKey);
}
/**
* 获取数据源
* @return 数据源标识
*/
public static String getDataSource() {
return contextHolder.get();
}
/**
* 清除数据源
*/
public static void clearDataSource() {
contextHolder.remove();
}
}
1.2、 配置动态数据源
需要配置一个 AbstractRoutingDataSource
来实现动态数据源的路由。
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSource();
}
}
1.3、 在Spring配置中定义数据源
在Spring配置中定义数据源,并将动态数据源配置为主数据源。
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
@Bean(name = "dataSource1")
@ConfigurationProperties(prefix = "spring.datasource.ds1")
public DataSource dataSource1() {