Spring Boot中实现多数据源连接和切换的方案

Spring Boot中实现多数据源连接和切换的方案

在Spring Boot项目中,随着业务需求的增长,我们往往需要连接多个数据库,即实现多数据源连接和切换。这种需求可能源于数据库的读写分离、微服务架构下的服务拆分、数据分库分表等场景。本文将详细探讨Spring Boot中实现多数据源连接和切换的多种方案,并给出相应的实现步骤和代码示例。

一、概述

在Spring Boot中,实现多数据源连接和切换的方案有多种,主要包括:

  1. 使用AbstractRoutingDataSource实现动态数据源切换
  2. 使用MP提供的Dynamic-datasource多数据源框架
  3. 通过自定义注解在方法或类上指定数据源
  4. 使用数据库代理中间件

每种方案都有其独特的优势和适用场景,下面将分别进行详细阐述。

二、使用AbstractRoutingDataSource实现动态数据源切换

AbstractRoutingDataSource是Spring框架提供的一个抽象类,用于根据用户定义的规则选择当前的数据源。通过继承这个类,并实现其抽象方法determineCurrentLookupKey,我们可以实现动态数据源切换。

步骤

  1. 定义数据源枚举:用于标识不同的数据源。
java 复制代码
public enum DataSourceType {
    MASTER("master"),
    SLAVE("slave");

    private String value;

    DataSourceType(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}
  1. 创建DynamicDataSource类:继承AbstractRoutingDataSource,并重写determineCurrentLookupKey方法。
java 复制代码
public class DynamicDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return CONTEXT_HOLDER.get();
    }

    public static void setDataSourceType(String dataSource) {
        CONTEXT_HOLDER.set(dataSource);
    }

    public static String getDataSourceType() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearDataSourceType() {
        CONTEXT_HOLDER.remove();
    }
}
  1. 配置数据源:在Spring Boot的配置文件中配置多个数据源,并在配置类中创建这些数据源,将它们注入到DynamicDataSource中。
java 复制代码
@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public DataSource dataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.getValue(), masterDataSource());
        targetDataSources.put(DataSourceType.SLAVE.getValue(), slaveDataSource());

        DynamicDataSource dataSource = new DynamicDataSource(masterDataSource(), targetDataSources);
        return dataSource;
    }
}
  1. 使用AOP切换数据源:通过自定义注解和AOP,在方法执行前后切换数据源。
java 复制代码
@Aspect
@Component
public class DataSourceAspect {

    @Before("@annotation(dataSource)")
    public void changeDataSource(JoinPoint point, DataSource dataSource) {
        DynamicDataSource.setDataSourceType(dataSource.value());
    }

    @After("@annotation(dataSource)")
    public void clearDataSource(JoinPoint point, DataSource dataSource) {
        DynamicDataSource.clearDataSourceType();
    }
}

自定义注解:

java 复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface DataSource {
    DataSourceType value() default DataSourceType.MASTER;
}
  1. 在业务方法上使用注解
java 复制代码
@Service
public class MyService {

    @DataSource(DataSourceType.SLAVE)
    public void someMethod() {
        // 业务逻辑
    }
}
三、使用MP提供的Dynamic-datasource多数据源框架

MP(MyBatis-Plus)提供了Dynamic-datasource多数据源框架,简化了多数据源的配置和管理。

步骤

  1. 引入依赖:在pom.xml文件中添加Dynamic-datasource的依赖。
xml 复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>
  1. 配置数据源:在application.yml或application.properties文件中配置多个数据源。
yaml 复制代码
spring:
  datasource:
    dynamic:
      primary: master # 设置默认的数据源或者数据源组,默认值即为master
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/master_db
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave:
          url: jdbc:mysql://localhost:3306/slave_db
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
  1. 使用注解或配置类指定数据源:在业务方法或配置类上使用@DS注解指定数据源。
java 复制代码
@Service
public class MyService {

    @DS("slave")
    public void someMethod() {
        // 业务逻辑
    }
}
四、通过自定义注解在方法或类上指定数据源

这种方案与使用AbstractRoutingDataSource实现动态数据源切换类似,但更加灵活和直观。通过自定义注解,我们可以直接在方法或类上指定使用哪个数据源。

步骤

  1. 定义数据源枚举和自定义注解(同上)。
  2. 创建数据源上下文类(同上)。
  3. 配置数据源(同上)。
  4. 使用AOP切换数据源(同上)。
  5. 在业务方法上使用注解(同上)。
五、使用数据库代理中间件

数据库代理中间件,如Mycat、Sharding-JDBC等,提供了更加灵活和强大的多数据源管理和分片功能。这些中间件通常支持读写分离、分库分表、数据聚合等功能,可以大大简化多数据源的配置和管理。

步骤

  1. 选择并引入中间件:根据业务需求选择合适的数据库代理中间件,并在项目中引入相应的依赖。
  2. 配置中间件:在配置文件中配置中间件的相关参数,如数据源、分片规则等。
  3. 使用中间件:通过中间件提供的接口或配置,实现多数据源连接和切换。
六、总结

在Spring Boot中实现多数据源连接和切换的方案有多种,每种方案都有其独特的优势和适用场景。使用AbstractRoutingDataSource实现动态数据源切换具有较高的灵活性和可控性;使用MP提供的Dynamic-datasource多数据源框架可以简化配置和管理;通过自定义注解在方法或类上指定数据源则更加直观和易用;使用数据库代理中间件则提供了更加灵活和强大的多数据源管理和分片功能。在实际应用中,我们可以根据业务需求和技术栈选择合适的方案,以实现多数据源连接和切换。

相关推荐
無限進步D4 小时前
Java 运行原理
java·开发语言·入门
難釋懷4 小时前
安装Canal
java
是苏浙4 小时前
JDK17新增特性
java·开发语言
不光头强4 小时前
spring cloud知识总结
后端·spring·spring cloud
GetcharZp7 小时前
告别 Python 依赖!用 LangChainGo 打造高性能大模型应用,Go 程序员必看!
后端
阿里加多7 小时前
第 4 章:Go 线程模型——GMP 深度解析
java·开发语言·后端·golang
likerhood7 小时前
java中`==`和`.equals()`区别
java·开发语言·python
小小李程序员7 小时前
Langchain4j工具调用获取不到ThreadLocal
java·后端·ai