Spring Boot实现多数据源连接和切换

embedded/2025/2/7 12:46:01/
文章目录
  • 前言
  • 一、多数据源配置与切换方案
  • 二、实现步骤
    • 1. 创建多个 `DataSource` 配置类
    • 2. 创建 `DataSource` 配置类
    • 3. 创建动态数据源路由类
    • 4. 实现 `DynamicDataSource` 类
    • 5. 创建 `DataSourceContextHolder` 来存储当前的数据源标识
    • 6. AOP 方式切换数据源
    • 7. 自定义注解来指定数据源
    • 8. 在 Service 层使用注解指定数据源
  • 总结

前言

在 Spring Boot 中实现多数据源连接和切换,可以通过以下几种方案来实现,具体取决于项目的需求、数据库的使用模式和管理的复杂性。以下是一个常见的多数据源切换的实现方案,使用 AbstractRoutingDataSource 来动态选择数据源。


一、多数据源配置与切换方案

在多数据源场景中,通常有如下步骤:

  • 配置多个数据源的 DataSource bean。
  • 使用 AbstractRoutingDataSource 来动态切换数据源。
  • 使用 ThreadLocal 存储当前的数据库类型或数据源标识符。
  • 配置数据源切换的逻辑,例如基于当前的用户、请求路径、服务标识等来选择不同的数据源。

二、实现步骤

1. 创建多个 DataSource 配置类

首先,为每个数据源创建单独的配置类,通常你会在 application.ymlapplication.properties 中配置每个数据源的连接信息。

spring:datasource:# 默认数据源配置primary:url: jdbc:mysql://localhost:3306/primary_dbusername: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverhikari:maximum-pool-size: 10# 第二数据源配置secondary:url: jdbc:mysql://localhost:3306/secondary_dbusername: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverhikari:maximum-pool-size: 10

2. 创建 DataSource 配置类

@Configuration
@EnableTransactionManagement
public class DataSourceConfig {@Bean(name = "primaryDataSource")@Primary@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();}
}

3. 创建动态数据源路由类

AbstractRoutingDataSource 允许我们在运行时根据某些条件动态选择数据源。

@Configuration
public class DynamicDataSourceConfig {@Autowired@Qualifier("primaryDataSource")private DataSource primaryDataSource;@Autowired@Qualifier("secondaryDataSource")private DataSource secondaryDataSource;@Beanpublic DataSource dataSource() {// 创建一个路由数据源DynamicDataSource dataSource = new DynamicDataSource();dataSource.setDefaultTargetDataSource(primaryDataSource); // 默认数据源Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("primary", primaryDataSource);targetDataSources.put("secondary", secondaryDataSource);dataSource.setTargetDataSources(targetDataSources);return dataSource;}
}

4. 实现 DynamicDataSource

DynamicDataSource 是继承自 AbstractRoutingDataSource,它通过 determineCurrentLookupKey() 方法来动态确定当前的数据源。

public class DynamicDataSource extends AbstractRoutingDataSource {// 从 ThreadLocal 获取当前的数据库标识@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSourceType();}
}

5. 创建 DataSourceContextHolder 来存储当前的数据源标识

使用 ThreadLocal 来保持当前线程的数据库标识,以便在不同的数据源之间切换。

public class DataSourceContextHolder {// 使用 ThreadLocal 存储当前线程的数据源标识private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();public static void setDataSourceType(String dataSourceType) {contextHolder.set(dataSourceType);}public static String getDataSourceType() {return contextHolder.get();}public static void clearDataSourceType() {contextHolder.remove();}
}

6. AOP 方式切换数据源

为了在运行时动态切换数据源,通常会使用 AOP 切面来拦截方法执行并指定数据源。

@Aspect
@Component
public class DataSourceAspect {// 通过注解来指定使用哪个数据源@Before("@annotation(dataSource)")public void switchDataSource(DataSourceType dataSource) {// 切换数据源DataSourceContextHolder.setDataSourceType(dataSource.value());}@After("@annotation(dataSource)")public void clearDataSource(DataSourceType dataSource) {// 清理数据源标识,避免影响其他线程DataSourceContextHolder.clearDataSourceType();}
}

7. 自定义注解来指定数据源

创建一个自定义注解 DataSourceType,用于指定当前方法执行时需要使用的数据源。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceType {String value() default "primary";  // 数据源标识,默认使用primary数据源
}

8. 在 Service 层使用注解指定数据源

在 Service 层,可以使用刚才创建的 @DataSourceType 注解来指定不同的方法使用不同的数据源。

@Service
public class UserService {@DataSourceType("primary")public List<User> getPrimaryUsers() {// 查询主数据库return userRepository.findAll();}@DataSourceType("secondary")public List<User> getSecondaryUsers() {// 查询次数据库return secondaryUserRepository.findAll();}
}

总结

  1. 数据源配置:为每个数据源配置 DataSource Bean。
  2. 动态数据源路由:使用 AbstractRoutingDataSource 来实现动态切换数据源。
  3. ThreadLocal存储:使用 ThreadLocal 存储和获取当前线程的数据源标识。
  4. AOP切换数据源:使用 AOP 来拦截方法并切换数据源。
  5. 注解方式指定数据源:通过自定义注解来指定方法使用的具体数据源。

这种方式比较灵活,能够在运行时根据业务需求选择不同的数据源,适用于多数据源的场景,尤其是分库分表、读写分离等复杂应用场景。


http://www.ppmy.cn/embedded/160301.html

相关文章

计算机网络知识速记:HTTP与HTTPS

计算机网络知识速记&#xff1a;HTTP与HTTPS 一、HTTP基础知识 HTTP&#xff08;超文本传输协议&#xff09;是一个无状态的协议&#xff0c;通常用于在客户端与服务器之间传输数据。HTTP采用的是一种请求-响应模型&#xff0c;客户端发出请求后&#xff0c;服务器返回数据。…

c++:vector

1.使用 1.1构造函数 常见的三种构造方式&#xff1a;空构造&#xff0c;拷贝构造&#xff0c;指定元素构造 1.2iterator begin和end也分为正向和反向。 注意&#xff1a;反向迭代器可以反向遍历是因为在定义rbegin和rend函数的时候把尾地址给到了rbegin&#xff0c;而不是说改…

流媒体娱乐服务平台在AWS上使用Presto作为大数据的交互式查询引擎的具体流程和代码

一家流媒体娱乐服务平台拥有庞大的用户群体和海量的数据。为了高效处理和分析这些数据&#xff0c;它选择了Presto作为其在AWS EMR上的大数据查询引擎。在AWS EMR上使用Presto取得了显著的成果和收获。这些成果不仅提升了数据查询效率&#xff0c;降低了运维成本&#xff0c;还…

基于Flask的商城应用系统的设计与实现

【FLask】基于Flask的商城应用系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统包括前端商城和后台管理系统&#xff0c;旨在为用户提供一个全面、便捷的在线购物平台及高…

大模型 RAG 优化之预生成qa对

1. 写在前面 检索增强生成 (Retrieval-Augmented Generation, RAG) 是一种将检索 (Retrieval) 和生成 (Generation) 相结合的技术,它利用检索到的相关信息来增强大型语言模型 (LLM) 的生成能力。传统的 RAG 系统通常直接使用用户输入的 query 在文档库中进行检索 (query-doc …

网件r7000刷回原厂固件合集测评

《网件R7000路由器刷回原厂固件详解》 网件R7000是一款备受赞誉的高性能无线路由器&#xff0c;其强大的性能和可定制性吸引了许多高级用户。然而&#xff0c;有时候用户可能会尝试第三方固件以提升功能或优化网络性能&#xff0c;但这也可能导致一些问题&#xff0c;如系统不…

Java面试:a+=a-=aa原理解析

Java面试&#xff1a;aa-a*a原理解析 aa-a*a属于Java基础中比较难以理解的&#xff0c;面试中也经常会遇到这个问题&#xff0c;本篇博客对此问题进行分享总结。 1.问题代码 public static void main(String[] args) {int a 2;aa-a*a;System.out.println("a"a);}我…

K8s 常见面试题(K8s Common Interview Questions)

K8s 常见面试题 k8s‌是一个开源的容器编排平台&#xff0c;用于管理云平台中多个主机上的容器化应用。Kubernetes的目标是使部署容器化的应用简单且高效&#xff0c;提供了应用部署、规划、更新和维护的一种机制‌。 定义和功能 Kubernetes&#xff08;简称K8s&#xff09;…