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多数据源框架可以简化配置和管理;通过自定义注解在方法或类上指定数据源则更加直观和易用;使用数据库代理中间件则提供了更加灵活和强大的多数据源管理和分片功能。在实际应用中,我们可以根据业务需求和技术栈选择合适的方案,以实现多数据源连接和切换。

相关推荐
蛋蛋的就会顺顺的36 分钟前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
余槐i44 分钟前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
需要8261 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡1 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
凤山老林2 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne3 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
张彦峰ZYF3 小时前
停顿短不等于延迟低:G1、ZGC 与低延迟服务的目标分野、代价账本与选型标定
后端·回收暂停、应用停止总时长·到达安全点、分配停滞·屏障吃吞吐、并发线程吃核心·并发窗口吃堆余量·分区式靠挑回收集兑现目标·染色指针式不支持压缩引用
silvamux_4 小时前
curl 测试 OpenAI 兼容 API 的完整流程
java·人工智能·缓存·ai·oneapi
pride.li4 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
省钱兄--zs4 小时前
深圳24小时自助健身房软硬件解决方案实战指南与开发流程详解
java·数据仓库·spring boot·小程序·架构