在Spring Boot中,当我们需要使用多数据源的时候,通常会面临一些挑战,比如如何动态切换数据源以及如何管理多个数据源的配置。为了解决这些问题,我们可以使用@DS
注解和自定义的DynamicDataSource
实现。这两种方式各有优缺点,适用于不同的场景。
一、@DS 注解的使用
@DS
注解是使用mybatis-plus
框架提供的,通常适合具有明确数据源标识的情况。通过这种方式,可以很方便地在服务层或者DAO层标识当前使用的数据源。
首先,在pom.xml
中添加mybatis-plus
依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
接下来,定义数据源的属性,比如在application.yml
中:
spring:
datasource:
ds1:
url: jdbc:mysql://localhost:3306/test1
username: root
password: password
ds2:
url: jdbc:mysql://localhost:3306/test2
username: root
password: password
然后,我们创建一个服务,使用@DS
注解选择数据源:
import com.baomidou.dynamic.datasource.annotation.DS;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@DS("ds1") // 使用第一个数据源
public void methodUsingDs1() {
// 调用 ds1 数据源的相关操作
}
@DS("ds2") // 使用第二个数据源
public void methodUsingDs2() {
// 调用 ds2 数据源的相关操作
}
}
通过这种方式,@DS 注解可以在方法级别上灵活切换数据源,非常适合某些方法需要显式指定数据源的场合。
二、DynamicDataSource自定义实现
当需要更灵活地管理多数据源时,可以选择自定义DynamicDataSource
。此实现适合于需要在运行时根据某些条件动态选择数据源的场景。
首先,我们定义一个数据源配置类,使用AbstractRoutingDataSource
来实现动态选择数据源:
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType(); // 获取当前线程绑定的数据源类型
}
}
接着,创建一个DataSourceContextHolder
用于存储和获取当前数据源类型:
public class DataSourceContextHolder {
private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();
public static void setDataSourceType(String dataSourceType) {
CONTEXT.set(dataSourceType);
}
public static String getDataSourceType() {
return CONTEXT.get();
}
public static void clearDataSourceType() {
CONTEXT.remove();
}
}
接下来,在配置类中配置数据源:
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.ds1")
public DataSource ds1() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.ds2")
public DataSource ds2() {
return DataSourceBuilder.create().build();
}
@Bean
public DynamicDataSource dataSource(@Qualifier("ds1") DataSource ds1,
@Qualifier("ds2") DataSource ds2) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("ds1", ds1);
targetDataSources.put("ds2", ds2);
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(ds1); // 设置默认数据源
return dynamicDataSource;
}
}
在使用时,我们可以通过DataSourceContextHolder
来设置当前操作使用的数据源:
public void someServiceMethod() {
try {
DataSourceContextHolder.setDataSourceType("ds1");
// 进行操作
} finally {
DataSourceContextHolder.clearDataSourceType(); // 清除当前数据源类型
}
}
总结
这两种方式各有利弊:
- 使用
@DS
注解更加简单,适用于明确需要使用不同数据源的场景。 - 自定义
DynamicDataSource
提供更大的灵活性,适用于需要程序逻辑决定数据源的复杂场景。
根据实际需求,可以选择合适的方式来实现多数据源的管理。