在 Java 框架 Spring 中,动态数据库的使用通常涉及根据不同条件(如请求的上下文、租户 ID 等)动态切换数据源。Spring 提供了一些方法来实现这一点,以下是一个常见的实现方案:
1. 基于 AbstractRoutingDataSource 实现动态数据库切换
Spring 提供了 AbstractRoutingDataSource
类,可以通过扩展该类来实现动态数据库路由。我们可以根据业务需求动态选择数据源。
步骤一:创建动态数据源路由类
首先,创建一个继承自 AbstractRoutingDataSource
的类,重写 determineCurrentLookupKey
方法。这个方法会根据当前上下文返回需要使用的数据源的标识符。
public class DynamicDataSourceRouter extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// 从 ThreadLocal 中获取当前数据源标识符
return DataSourceContextHolder.getDataSource();
}
}
DataSourceContextHolder
是一个自定义的工具类,用于在 ThreadLocal 中保存当前数据源标识符:
public class DataSourceContextHolder {
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
CONTEXT_HOLDER.set(dataSource);
}
public static String getDataSource() {
return CONTEXT_HOLDER.get();
}
public static void clearDataSource() {
CONTEXT_HOLDER.remove();
}
}
步骤二:配置多个数据源
在 Spring 的配置类中,配置多个数据源,并将其注入到 DynamicDataSourceRouter
中。
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("dataSource1", dataSource1());
targetDataSources.put("dataSource2", dataSource2());
DynamicDataSourceRouter dynamicDataSourceRouter = new DynamicDataSourceRouter();
dynamicDataSourceRouter.setDefaultTargetDataSource(dataSource1()); // 设置默认数据源
dynamicDataSourceRouter.setTargetDataSources(targetDataSources);
return dynamicDataSourceRouter;
}
@Bean
public DataSource dataSource1() {
// 配置数据源1
}
@Bean
public DataSource dataSource2() {
// 配置数据源2
}
}
步骤三:在业务层切换数据源
在业务层中,可以通过调用 DataSourceContextHolder
来切换当前数据源:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public void switchDataSourceAndExecute(String dataSourceKey) {
try {
DataSourceContextHolder.setDataSource(dataSourceKey);
// 执行数据库操作
userRepository.findAll();
} finally {
DataSourceContextHolder.clearDataSource(); // 清理数据源,恢复默认
}
}
}
2. 使用 Spring Boot 多数据源配置
在 Spring Boot 项目中,还可以通过配置文件来定义多个数据源,并手动切换或使用 @Primary
注解指定默认数据源。
配置文件定义多个数据源
在 application.yml
或 application.properties
文件中定义多个数据源:
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/primary_db
username: root
password: password
secondary:
url: jdbc:mysql://localhost:3306/secondary_db
username: root
password: password
配置多个数据源 Bean
在配置类中定义多个数据源 Bean:
@Configuration
public class MultiDataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
使用不同的数据源
在 DAO 层或 Service 层中,通过 @Qualifier
注解指定使用的数据库源:
@Service
public class ProductService {
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
public void someMethod() {
// 使用 primaryDataSource 执行操作
}
public void anotherMethod() {
// 使用 secondaryDataSource 执行操作
}
}
3. 使用第三方库如 Spring Cloud 或 ShardingSphere
对于更复杂的场景,如分库分表、微服务环境中的多数据源管理,可以考虑使用 ShardingSphere、Spring Cloud 等第三方库,它们提供了更加丰富的功能支持动态数据库切换。
总结
通过以上方法,Spring 框架可以轻松实现动态数据库的管理和切换。无论是通过 AbstractRoutingDataSource
的自定义实现,还是通过 Spring Boot 的多数据源配置,都可以在不同场景下有效应用。