当前位置: 首页 > 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.dtcms.com/a/322834.html

相关文章:

  • Redis分布式锁详解:原理、实现与实战案例
  • 【C++11新特性】智能指针,右值引用,移动语义与完美转发,函数对象...
  • Linux运维新手的修炼手扎之第27天
  • pyqt5 ECU编辑demo
  • NX二次开发——面有关的函数
  • 1.2.3 迅猛发展期(2020年至今)
  • 让大模型 “睡觉”:把版本迭代当作人类睡眠来设计(附可直接改造的训练作息表与代码)
  • 104-基于Flask的优衣库销售数据可视化分析系统
  • 100-基于Python的智联招聘数据可视化分析推荐系统
  • 一周学会Matplotlib3 Python 数据可视化-网格 (Grid)
  • 力扣(删除有序数组中的重复项I/II)
  • [优选算法专题一双指针——四数之和]
  • 配送算法10 Batching and Matching for Food Delivery in Dynamic Road Networks
  • Java 8特性(一)
  • 新手向:Python开发简易待办事项应用
  • 顺风车软件系统架构分析
  • 大语言模型提示工程与应用:ChatGPT提示工程技术指南
  • PDF编辑工具,免费OCR识别表单
  • ST语法介绍
  • GloVe词向量:原理详解及用python进行训练和应用GloVe
  • 【第四章:大模型(LLM)】05.LLM实战: 实现GPT2-(1)文本token到Embedding的代码实现
  • 【数据分享】各省农业土地流转率(2010-2023)
  • Easysearch 冷热架构实战
  • 分治-快排-面试题 17.14.最小k个数-力扣(LeetCode)
  • Redhat Linux 9.6 配置本地 yum 源
  • 【数据结构入门】栈和队列
  • 网盘短剧资源转存项目源码 支持垮克 带后台 附教程
  • Kafka服务端NIO操作原理解析(二)
  • MX 播放器:安卓设备上的全能视频播放器
  • 【解决方法】华为电脑的亮度调节失灵