Spring Boot动态数据源切换功能详解

在现代软件开发中,尤其是在处理复杂业务逻辑时,经常需要从多个数据源中读取或写入数据。Spring Boot作为一个流行的Java框架,提供了强大的数据源配置功能,使得动态数据源切换变得相对简单。本文将详细介绍如何在Spring Boot应用中实现动态数据源切换。

准备工作

在开始实现动态数据源切换之前,我们需要做一些准备工作:

  1. 创建Spring Boot项目:

    • 可以使用Spring Initializr快速生成项目骨架。在创建项目时,选择合适的JDK版本、项目构建工具(如Maven或Gradle)以及项目元数据(如项目名称、描述、包名等)。
  2. 添加依赖:

    • 在项目的pom.xml文件中添加必要的依赖。例如:

      xml 复制代码
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-jdbc</artifactId>
      </dependency>
      <dependency>
          <groupId>com.zaxxer</groupId>
          <artifactId>HikariCP</artifactId>
      </dependency>
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
      </dependency>
实现动态数据源切换

接下来,我们将介绍如何实现动态数据源切换。主要分为以下几个步骤:

  1. 配置数据源:

    • 在application.properties或application.yml文件中配置多个数据源。例如:

      yaml 复制代码
      spring:
        datasource:
          primary:
            url: jdbc:mysql://localhost:3306/primary_db
            username: root
            password: password
            driver-class-name: com.mysql.cj.jdbc.Driver
          secondary:
            url: jdbc:mysql://localhost:3306/secondary_db
            username: root
            password: password
            driver-class-name: com.mysql.cj.jdbc.Driver
  2. 定义数据源配置类:

    • 创建一个数据源配置类,用于配置多数据源。例如:

      java 复制代码
      package cn.juwatech.config;
      
      import com.zaxxer.hikari.HikariDataSource;
      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;
      
      @Configuration
      public class DataSourceConfig {
      
          @Primary
          @Bean(name = "primaryDataSource")
          @ConfigurationProperties("spring.datasource.primary")
          public HikariDataSource primaryDataSource() {
              return new HikariDataSource();
          }
      
          @Bean(name = "secondaryDataSource")
          @ConfigurationProperties("spring.datasource.secondary")
          public HikariDataSource secondaryDataSource() {
              return new HikariDataSource();
          }
      }
  3. 定义数据源上下文和切换器:

    • 创建一个数据源上下文类,用于存储当前线程使用的数据源。例如:

      java 复制代码
      package cn.juwatech.datasource;
      
      public class DataSourceContextHolder {
          private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
      
          public static void setDataSource(String dataSource) {
              contextHolder.set(dataSource);
          }
      
          public static String getDataSource() {
              return contextHolder.get();
          }
      
          public static void clearDataSource() {
              contextHolder.remove();
          }
      }
    • 创建一个数据源切换器,用于动态切换数据源。例如:

      java 复制代码
      package cn.juwatech.datasource;
      
      import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
      
      public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
          @Override
          protected Object determineCurrentLookupKey() {
              return DataSourceContextHolder.getDataSource();
          }
      }
  4. 配置动态数据源:

    • 在配置类中使用动态数据源。例如:

      java 复制代码
      package cn.juwatech.config;
      
      import cn.juwatech.datasource.DynamicRoutingDataSource;
      import org.springframework.beans.factory.annotation.Qualifier;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.jdbc.datasource.DataSourceTransactionManager;
      
      import javax.sql.DataSource;
      import java.util.HashMap;
      import java.util.Map;
      
      @Configuration
      public class DataSourceConfig {
      
          @Primary
          @Bean(name = "primaryDataSource")
          @ConfigurationProperties("spring.datasource.primary")
          public DataSource primaryDataSource() {
              return new HikariDataSource();
          }
      
          @Bean(name = "secondaryDataSource")
          @ConfigurationProperties("spring.datasource.secondary")
          public DataSource secondaryDataSource() {
              return new HikariDataSource();
          }
      
          @Bean
          public DataSource dataSource() {
              Map<Object, Object> targetDataSources = new HashMap<>();
              targetDataSources.put("primaryDataSource", primaryDataSource());
              targetDataSources.put("secondaryDataSource", secondaryDataSource());
      
              DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource();
              routingDataSource.setDefaultTargetDataSource(primaryDataSource());
              routingDataSource.setTargetDataSources(targetDataSources);
      
              return routingDataSource;
          }
      }
使用动态数据源

在业务代码中,根据业务逻辑和条件设置ThreadLocal中的数据源信息。例如:

java 复制代码
DataSourceContextHolder.setDataSource("secondaryDataSource"); // 设置当前线程的数据源为secondary

在数据访问层(如DAO),使用动态数据源来获取数据源并执行查询。MyBatis-Plus会根据ThreadLocal中的数据源信息来决定从哪个数据源中获取数据。当业务逻辑执行完成后,记得清除ThreadLocal中的数据源信息,以避免对其他线程造成影响。

总结

通过上述步骤,我们实现了在Spring Boot应用中动态切换数据源的功能。这不仅可以提高应用程序的灵活性和可扩展性,还能满足复杂业务逻辑下的数据处理需求。在实际开发中,可以根据具体业务需求进行进一步的优化和扩展。

相关推荐
Highcharts.js31 分钟前
Highcharts智能数据分析平台Orbit 多语言配置技术文档
java·前端·javascript·highcharts·orbit·智能数据分析·设置文档
Rain的Java大神之路39 分钟前
设计一套生产级 API 接口:从契约、安全、幂等到限流,我踩过的坑都在这了
java·后端·面试
SimonKing41 分钟前
零配置也能白嫖前沿大模型!dsh-our-free-model插件真香警告
java·后端·程序员
nice_lcj52042 分钟前
【从零理解 Spring AI · 15】让检索更准:先宽召回,再精排序
java·后端·rag·spring ai·ai应用开发·检索优化·重排序
回家路上绕了弯1 小时前
要人确认的那一步,在确认什么?
后端
IT_陈寒2 小时前
JavaScript项目实战经验分享:从内存泄漏到性能优化的血泪史
前端·人工智能·后端
杨凯凡2 小时前
Spring Boot 链路追踪实战:Micrometer、TraceId 与异步线程上下文传播
java·spring boot·后端
计算机毕设定制辅导-无忧学长2 小时前
《基于Spring Boot的迷游哈游戏综合服务平台的开发》
java·vue.js·spring boot·mysql·迷游哈游戏综合服务平台
非优秀程序员11 小时前
第07章 孙德良的阳谋|《互联网产品恩仇录》
javascript·后端
非优秀程序员11 小时前
第06章 浙江帮的内战|《互联网产品恩仇录》
后端