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

server/2024/11/13 2:24:14/

文章目录

  • 前言
  • 一、多数据源配置与切换方案
  • 二、实现步骤
    • 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 配置类

java">@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 允许我们在运行时根据某些条件动态选择数据源。

java">@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() 方法来动态确定当前的数据源。

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

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

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

java">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 切面来拦截方法执行并指定数据源。

java">@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,用于指定当前方法执行时需要使用的数据源。

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

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

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

java">@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/server/140748.html

相关文章

Apache POI 操作Word常用方法

系列文章目录 一、Java使用Apache POI导出excel 二、Apache POI 操作Excel常用方法 三、Apache poi 拆分单元格并赋值 四、使用easypoi模板方法导出excel 五、Apache poi给excel单元格添加下拉框或数据验证 六、Apache poi操作Word常用方法 文章目录 系列文章目录一、介绍二、…

M芯片Mac构建Dockerfile - 注意事项

由于MacBook的M芯片架构与intel不同&#xff0c;交叉构建Linux服务器docker镜像&#xff0c;需要以下步骤完成&#xff1a; 编写好Dockerfile在命令行中&#xff0c;执行构建命令&#xff1a; docker buildx build --platform linux/amd64 -t ${image_name}:${tag} .

机器视觉基础—双目相机

机器视觉基础—双目相机与立体视觉 双目相机概念与测量原理 我们多视几何的基础就在于是需要不同的相机拍摄的同一个物体的视场是由重合的区域的。通过下面的这种几何模型的目的是要得到估计物体的长度&#xff0c;或者说是离这个相机的距离。&#xff08;深度信息&#xff09…

JAVA基础:单元测试;注解;枚举;网络编程 (学习笔记)

单元测试 操作步骤&#xff1a; a.导包import org.junit; b.三个注解 Test Before After c.点击Test 运行就可以了 用在不需要控制台输入的情境下&#xff1a;javaweb&#xff0c;框架项目&#xff0c;微服务项目 供开发人员自己做测试。 package com.page…

【微服务】不同微服务之间用户信息的获取和传递方案

如何才能在每个微服务中都拿到用户信息&#xff1f;如何在微服务之间传递用户信息&#xff1f; 文章目录 概述利用微服务网关做登录校验网关转微服务获取用户信息openFeign传递微服务之间的用户信息 概述 要在每个微服务中获取用户信息&#xff0c;可以采用以下几种方法&#…

海康威视摄像头ISUP(原EHOME协议) 摄像头实时预览springboot 版本java实现,并可以在浏览器vue前端播放(附带源码)

1.首先说了一下为什么要用ISUP协议来取流 ISUP主要就是用来解决摄像头没有公网ip的情况,如果摄像头或者所在局域网的路由器有公网ip的话&#xff0c;其实采用rtsp直接取流是最方便也是性能最好的&#xff0c;但是项目的摄像头没有公网IP所以被迫使用ISUP&#xff0c;ISUP是海康…

LVGL加入外围字库

一、首先lvgl是有自带字库的 lvgl/src/font 如下图 二、但如果这个字库不能满足我们的需求我们就要外建字库。 1、字库生成软件LVGL官网&#xff0c;字体转换器 — LVGL如下图&#xff1a; 最后按“提交”就可以看到有一个字体被下载到你电脑里。他是以.c文件的型式&#xff0…

mybatis-plus 长sql执行缓慢问题

说起这个问题&#xff0c;可把我坑苦了&#xff0c;这个问题一共找了两次&#xff0c;第一次是因为一个sql执行缓慢&#xff0c;我来排查原因&#xff0c;先后排除了sql本身的问题&#xff0c;网络问题&#xff0c;项目代码问题&#xff0c;数据库压力问题&#xff0c;最后问题…