当前位置: 首页 > news >正文

在Spring Boot项目中如何动态切换数据源、数据库?

全文目录:

    • 开篇语
    • 前言
    • 动态切换数据源的需求
    • 步骤一:引入相关依赖
    • 步骤二:配置多个数据源
      • 示例:主库(Primary DataSource)配置
      • `application.properties` 配置文件
    • 步骤三:自定义动态数据源
      • 1. 自定义`AbstractRoutingDataSource`类
      • 2. 定义`DataSourceContextHolder`类
      • 3. 配置`DynamicDataSource`为数据源
    • 步骤四:使用动态数据源
      • 示例:在业务方法中切换数据源
      • 在控制器中切换数据源
    • 步骤五:使用AOP统一切换数据源
      • 1. 自定义注解
      • 2. 切面实现
      • 3. 使用注解切换数据源
    • 总结
    • 文末

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在一些复杂的企业级应用中,可能会有多个数据库的使用需求,比如读写分离、数据库分库、不同业务模块使用不同数据库等。Spring Boot作为一种快速开发框架,提供了强大的配置和扩展能力,可以实现动态切换数据源和数据库。

  本文将介绍在Spring Boot项目中,如何实现动态切换数据源和数据库,包括切换的原理、步骤和实现方式。我们将使用Spring的AbstractRoutingDataSource实现多数据源动态切换。

动态切换数据源的需求

在实际开发中,我们可能会遇到以下几种需求:

  • 读写分离:将写操作和读操作分别使用不同的数据库,以提高数据库的性能。
  • 多数据库支持:项目需要支持多个数据库,比如主库和备库、不同业务模块使用不同的数据库。
  • 按条件切换数据源:根据特定的条件(如用户、请求来源等)选择不同的数据源。

为了满足这些需求,我们可以利用Spring提供的动态数据源功能,通过自定义一个AbstractRoutingDataSource,在每次操作时动态地选择不同的数据源。

步骤一:引入相关依赖

首先,确保你的Spring Boot项目中已经包含了JPA、DataSource等相关依赖。如果使用的是Spring Boot 2.x及以上版本,通常会自动引入这些依赖,但仍需确认在pom.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>

步骤二:配置多个数据源

首先,定义两个或更多的数据源配置类,并配置数据源的基本信息。比如,我们配置主库(primaryDataSource)和从库(secondaryDataSource)。

示例:主库(Primary DataSource)配置

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

application.properties 配置文件

application.properties文件中,配置主库和从库的数据库连接信息:

# 主数据库配置
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.primary.username=root
spring.datasource.primary.password=root_password
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.primary.hikari.maximum-pool-size=10# 从数据库配置
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondary_db
spring.datasource.secondary.username=root
spring.datasource.secondary.password=root_password
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.secondary.hikari.maximum-pool-size=10

步骤三:自定义动态数据源

1. 自定义AbstractRoutingDataSource

AbstractRoutingDataSource是Spring提供的一个用于动态切换数据源的抽象类。我们需要继承该类并重写determineCurrentLookupKey()方法,该方法用于决定当前请求使用哪个数据源。

public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {// 根据当前的上下文选择数据源return DataSourceContextHolder.getDataSourceType();}
}

2. 定义DataSourceContextHolder

DataSourceContextHolder类用于保存当前线程的数据源信息。它通过ThreadLocal来存储数据源,以确保线程安全。

public class DataSourceContextHolder {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();}
}

3. 配置DynamicDataSource为数据源

在数据源配置中,将DynamicDataSource配置为数据源,确保它能够根据DataSourceContextHolder中存储的数据源类型动态切换。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.example.repository")
public class DataSourceConfig {@Primary@Beanpublic DynamicDataSource dynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("primary", primaryDataSource);targetDataSources.put("secondary", secondaryDataSource);DynamicDataSource dynamicDataSource = new DynamicDataSource();dynamicDataSource.setDefaultTargetDataSource(primaryDataSource);dynamicDataSource.setTargetDataSources(targetDataSources);return dynamicDataSource;}
}

步骤四:使用动态数据源

在使用动态数据源时,通常是在特定的业务逻辑中切换数据源。例如,您可以在服务层或控制器层根据不同的业务需求来切换数据源。

示例:在业务方法中切换数据源

@Service
public class DataService {public void usePrimaryDataSource() {// 切换到主数据库DataSourceContextHolder.setDataSourceType("primary");// 执行主数据库相关操作}public void useSecondaryDataSource() {// 切换到从数据库DataSourceContextHolder.setDataSourceType("secondary");// 执行从数据库相关操作}public void clearDataSource() {// 清除数据源设置,恢复默认DataSourceContextHolder.clearDataSourceType();}
}

在控制器中切换数据源

@RestController
@RequestMapping("/data")
public class DataController {@Autowiredprivate DataService dataService;@GetMapping("/usePrimary")public String usePrimaryDataSource() {dataService.usePrimaryDataSource();return "Used Primary DataSource";}@GetMapping("/useSecondary")public String useSecondaryDataSource() {dataService.useSecondaryDataSource();return "Used Secondary DataSource";}
}

步骤五:使用AOP统一切换数据源

为了更好地解耦数据源切换逻辑,可以使用AOP(面向切面编程)来统一处理数据源切换。我们可以定义一个AOP切面,在方法执行前根据注解或其他条件自动切换数据源。

1. 自定义注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSourceSwitch {String value() default "primary"; // 默认使用主数据库
}

2. 切面实现

@Aspect
@Component
public class DataSourceAspect {@Before("@annotation(dataSourceSwitch)")public void switchDataSource(DataSourceSwitch dataSourceSwitch) {String dataSourceType = dataSourceSwitch.value();DataSourceContextHolder.setDataSourceType(dataSourceType);}@After("@annotation(dataSourceSwitch)")public void clearDataSource(DataSourceSwitch dataSourceSwitch) {DataSourceContextHolder.clearDataSourceType();}
}

3. 使用注解切换数据源

@Service
public class DataService {@DataSourceSwitch("primary")public void usePrimaryDataSource() {// 使用主数据库}@DataSourceSwitch("secondary")public void useSecondaryDataSource() {// 使用从数据库}
}

总结

在Spring Boot项目中动态切换数据源是一个常见需求,特别是当涉及到读写分离、分库等复杂场景时。通过继承AbstractRoutingDataSource并结合ThreadLocal来保存当前数据源信息,我们可以实现灵活的数据源切换。此外,通过AOP和自定义注解,我们可以更加优雅和解耦地实现数据源的动态切换。在多数据源的项目中,掌握这种动态切换的实现方法,对于提升项目的可扩展性和可维护性具有重要意义。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

http://www.lryc.cn/news/615333.html

相关文章:

  • java -jar xxx.jar 提示xxx.jar中没有主清单属性报错解决方案
  • 【Git】Visual Studio 实现合并分支
  • Alibaba Cloud Linux 3 安装 git
  • DigitalProductId解密算法php调试版piddebug.php
  • n8n飞书webhook配置(飞书机器人、飞书bot、feishu bot)Crypto节点、js timestamp代码、Crypto node
  • AG32cpld实现一个UartTx“外设”
  • Kafka服务端NIO操作原理解析(二)
  • Arm Development Studio 安全通告:CVE-2025-7427
  • 人脸情绪检测数据集-9,400 张图片 智能客服系统 在线教育平台 心理健康监测 人机交互优化 市场研究与广告 安全监控系统
  • 【面试题】cookie和session 的区别
  • 【26】C#实战篇—— 多个线程函数对同一个 Excel 文件进行写操作引起的文件冲突问题,解决方法
  • Playwright C# 自动登录并上传 Excel 文件 的可运行示例
  • Irix HDR Pro:专业级 HDR 图像处理软件
  • Docker部署whisper转写模型
  • Java中Lambda表达式的常见用法和解析:从入门到实战
  • C/C++基础详解(二)
  • 【51单片机4按键启动停止向上向下流水灯】2022-10-26
  • 本文章分享一个本地录音和实时传输录音给app的功能(杰理)
  • 【c++】探秘Loop机制:C++中优雅的双向数据交互模式
  • Ubuntu下安全彻底删除后端服务完整指南
  • 网络原理-初识
  • PNPM总结
  • QT第一讲- Qt初探
  • Microsoft Office Visio(流程图)学习笔记
  • 使用SymPy lambdify处理齐次矩阵的高效向量化计算
  • 动手学深度学习(pytorch版):第二章节——预备知识(1)——数据操作
  • 2025华数杯数学建模C题:可调控生物节律LED光源全解析
  • 理解协议最大传输单元(MTU)和TCP 最大报文段长度(MSS)
  • 自动生成视频的AI大模型高效创作指南
  • 掌握数据可视化:全局配置项详解