Spring Boot 动态数据源的配置和使用——附实例教程

news2024/9/21 20:37:22

文章目录

      • 1. 添加依赖
      • 2. 配置数据源
      • 3. 创建 `DynamicDataSource` 类
      • 4. 创建 `DynamicDataSourceContextHolder`
      • 5. 配置数据源切换 AOP
      • 6. 自定义注解 `@DataSource`
      • 7. 使用示例
      • 8. 配置文件 `application.yml`
      • 9. 总结

在 Spring Boot 中,动态数据源的配置和使用可以通过 AbstractRoutingDataSource 类实现,它允许在运行时动态切换数据源。以下是一个简单的配置和使用示例。

1. 添加依赖

首先在 pom.xml 文件中添加相关的数据库和 MyBatis 依赖:

<dependencies>
    <!-- Spring Boot Starter for Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- HikariCP 数据源 -->
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>

    <!-- MyBatis 支持 -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>
</dependencies>

含义

  • spring-boot-starter-data-jpa: 提供 Spring Data JPA 的支持,方便处理数据库操作。
  • mysql-connector-java: MySQL 驱动,用于连接 MySQL 数据库。
  • HikariCP: 高性能数据源连接池实现。
  • mybatis-spring-boot-starter: 提供 MyBatis 对 Spring Boot 的支持,方便使用 MyBatis 进行数据库操作。

这些依赖是项目中所需的核心组件,帮助进行数据库连接、操作和数据源管理。


2. 配置数据源

创建一个配置类来定义多个数据源。

@Configuration
public class DataSourceConfig {

    @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();
    }

    @Bean(name = "dynamicDataSource")
    public DataSource 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;
    }
}

含义

  • @Configuration: 标记该类为配置类,Spring Boot 会自动扫描并处理其中的 @Bean 定义。
  • primaryDataSource()secondaryDataSource(): 定义两个不同的数据源,通过 @ConfigurationPropertiesapplication.yml 中读取配置。
  • dynamicDataSource(): 定义动态数据源,将多个数据源放入 targetDataSources 中,并设置一个默认的数据源(primary)。返回的 DynamicDataSource 实现允许应用程序在运行时切换数据源。

3. 创建 DynamicDataSource

这个类继承自 AbstractRoutingDataSource,用于动态决定使用哪个数据源。

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }
}

含义

  • DynamicDataSource: 继承 AbstractRoutingDataSource,它负责决定当前使用哪个数据源。AbstractRoutingDataSource 是 Spring 提供的一个类,可以基于业务逻辑动态选择数据源。
  • determineCurrentLookupKey(): 根据当前线程保存的数据库类型,决定要使用的具体数据源。具体的数据库类型是通过 DynamicDataSourceContextHolder 设置和获取的。

4. 创建 DynamicDataSourceContextHolder

创建 DynamicDataSourceContextHolder 用于保存当前线程的数据库类型

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

含义

  • ThreadLocal: 用于在线程内部保存数据库类型。这样每个线程可以独立设置和获取当前使用的数据源类型。
  • setDataSourceType(): 设置当前线程的数据源类型。
  • getDataSourceType(): 获取当前线程的数据源类型。
  • clearDataSourceType(): 清除当前线程的数据源类型。

这个类相当于一个工具类,用来管理和存储当前使用的数据源。


5. 配置数据源切换 AOP

通过 AOP 在服务层方法中动态切换数据源。

@Aspect
@Component
public class DynamicDataSourceAspect {

    @Before("@annotation(ds)")
    public void switchDataSource(JoinPoint point, DataSource ds) {
        DynamicDataSourceContextHolder.setDataSourceType(ds.value());
    }

    @After("@annotation(ds)")
    public void clearDataSource(JoinPoint point, DataSource ds) {
        DynamicDataSourceContextHolder.clearDataSourceType();
    }
}

含义

  • @Aspect: 声明该类为一个 AOP 切面,允许在目标方法执行前后执行额外的逻辑。
  • @Before@After: 在带有 @DataSource 注解的方法执行前后切换数据源。
  • switchDataSource(): 在方法执行之前,根据注解值设置当前线程的数据源类型。
  • clearDataSource(): 在方法执行后清除数据源类型,避免影响后续的操作。

6. 自定义注解 @DataSource

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String value() default "primary";
}

含义

  • @Target: 指定该注解可以用在方法和类上。
  • @Retention: 指定注解的生命周期是运行时,允许反射获取注解信息。
  • @Documented: 使注解成为文档的一部分。
  • @interface DataSource: 自定义注解,用来标识在哪些地方需要切换数据源。

此注解可以用来标记方法或类,指定该方法或类使用哪个数据源。


7. 使用示例

在服务层方法上使用注解切换数据源。

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @DataSource("primary")
    public List<User> getAllUsersFromPrimary() {
        return userMapper.getAllUsers();
    }

    @DataSource("secondary")
    public List<User> getAllUsersFromSecondary() {
        return userMapper.getAllUsers();
    }
}

含义

  • @DataSource("primary")@DataSource("secondary"): 在不同的方法上使用自定义注解,表示该方法执行时使用不同的数据源。
  • 这样在调用 getAllUsersFromPrimary() 时,程序会使用主数据源,而调用 getAllUsersFromSecondary() 时,会使用从数据源。

8. 配置文件 application.yml

在 application.yml 中配置多个数据源:

spring:
  datasource:
    primary:
      url: jdbc:mysql://localhost:3306/primary_db
      username: root
      password: password
      driver-class-name: com.mysql.cj.jdbc.Driver
    secondary:
      url: jdbc:mysql://localhost:3306/secondary_db
      username: root
      password: password
      driver-class-name: com.mysql.cj.jdbc.Driver

含义

  • application.yml 中配置两个不同的数据库连接,一个为主数据库(primary),一个为从数据库(secondary)。这些配置将会被 DataSourceConfig 类中的 @ConfigurationProperties 自动读取,用来初始化对应的数据源。

9. 总结

整个流程使用了 Spring Boot 提供的 AbstractRoutingDataSource 机制,通过动态切换不同的数据源,支持在运行时决定应用程序使用的数据库。每个步骤紧密配合,确保在应用运行时根据不同的业务需求选择合适的数据源。

通过 @DataSource 注解,可以灵活地在服务层方法中进行数据源切换,而不需要手动管理数据库连接逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2153251.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nature Communications|一种快速响应的智能可穿戴嗅觉接口(可穿戴电子/柔性电子/人机交互)

香港城市大学于欣格( Xinge Yu)、北京航空航天大学李宇航(Yuhang Li)、中国特种设备检验研究所赵召(Zhao Zhao)和东京大学Takao Someya团队,在《Nature Communications》上发布了一篇题为“Intelligent wearable olfactory interface for latency-free mixed reality and …

云盘视频保护神器,支持云盘视频加密与在线播放,配合alist使用,超完美!

平时我们保护视频&#xff0c;一般都是采用压缩工具&#xff0c;进行加密打包&#xff0c;然后在上传到网盘存储。这虽然能起到很好的保护&#xff0c;但是有很多问题&#xff1f;比如&#xff1a;无法直接在线播放&#xff0c;还得从网盘中下载后解压&#xff0c;才能进行观看…

【Python语言初识(一)】

一、python简史 1.1、python的历史 1989年圣诞节&#xff1a;Guido von Rossum开始写Python语言的编译器。1991年2月&#xff1a;第一个Python编译器&#xff08;同时也是解释器&#xff09;诞生&#xff0c;它是用C语言实现的&#xff08;后面&#xff09;&#xff0c;可以调…

计算机人工智能前沿进展-大语言模型方向-2024-09-21

计算机人工智能前沿进展-大语言模型方向-2024-09-21 1. AIvril: AI-Driven RTL Generation With Verification In-The-Loop Authors: Mubashir ul Islam, Humza Sami, Pierre-Emmanuel Gaillardon, and Valerio Tenace AIVRIL: 人工智能驱动的RTL生成与验证内循环 摘要 本…

allWebPlugin中间件自定义alert、confirm及prompt使用

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

通信工程学习:什么是WLAN无线局域网

WLAN&#xff1a;无线局域网 WLAN&#xff08;Wireless Local Area Network&#xff09;&#xff0c;即无线局域网&#xff0c;是一种利用无线技术实现局域网内设备间数据传输的网络系统。以下是对WLAN无线局域网的详细解释&#xff1a; 一、WLAN无线局域网的定义与概述 WLAN通…

python-3n+1数链/233

一&#xff1a;3n1数链题目描述 在计算机科学上&#xff0c;有很多类问题是无法解决的&#xff0c;我们称之为不可解决问题。然而&#xff0c;在很多情况下我们并不知道哪一类问题可以解决&#xff0c;哪一类问题不可解决。现在我们就有这样一个问题&#xff0c;问题如下&#…

Qt-QLabel 添加图片并设置 GIF 图动态效果

Qt-QLabel 添加图片并设置 GIF 图动态效果 一、添加图片资源并设置图片 选择标签&#xff0c;拖拉到界面上&#xff0c;然后选择器属性 picmap   选择设置&#xff0c;在这里添加图片资源   点击左边的加号符号按钮添加前缀&#xff0c;并设置前缀名&#xff0c;如果已经…

C++速通LeetCode中等第20题-随机链表的复制(三步简单图解)

方法图解&#xff1a; class Solution { public:Node* copyRandomList(Node* head) {if ( !head ) {return nullptr;}Node *cur head;// 1. 在原节点的每个节点后创建一个节点while ( cur ) {Node *newNode new Node(cur -> val);newNode -> next cur -> next;cur …

一篇进阶Python深入理解函数之高阶函数与函数式编程

当我们深入探讨了函数的作用域与闭包,了解到函数不仅是代码的执行单元,还能通过闭包完成数据的封装与保护.接下来,我们将进一步挖掘函数的强大特性,尤其是高阶函数与函数式编程,帮助你更全面地理解 Python 中函数的特性与应用. 高阶函数 高阶函数是指接受一个或多个函数作为参…

混合开发-JSBridge

1.1 什么是混合开发? 混合开发是一种融合了原生开发和Web开发优势的移动应用开发方式。 具体来说&#xff0c;混合开发通常指的是利用一种框架或平台来创建应用程序&#xff0c;这种程序结合了原生应用的一些功能和特性&#xff08;比如访问设备的摄像头、相册、GPS、蓝牙等…

Excel 冻结多行多列

背景 版本&#xff1a;office 2021 专业版 无法像下图内某些版本一样&#xff0c;识别选中框选的多行多列。 如下选中后毫无反应&#xff0c;点击【视图】->【冻结窗口】->【冻结窗格】后自动设置为冻结第一列。 操作 如下&#xff0c;要把前两排冻结起来。 选择 C1&a…

华为OD机试 - 信号强度(Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

网站渗透这块水太深,你把握不住!但你叔我能(十年经验分享)

很多朋友问我&#xff0c;想搞网络安全&#xff0c;编程重要吗&#xff0c;选什么语言呢&#xff1f; 国内其实正经开设网络安全专业的学校很少&#xff0c;大部分同学是来自计算机科学、网络工程、软件工程专业的&#xff0c;甚至很多非计算机专业自学的。因此不像这三个专业…

【技术文章】ArcGIS Pro如何批量导出符号和工程样式?

目录 1.确定Pro软件版本 2.共享工程样式 3.管理和调用项目样式 制作好的地图&#xff0c;如何快速分享地图中的符号样式用于其它地图的制作&#xff1f; 在ArcMap软件中&#xff0c;可以通过命令一键批量导出所有符号。ArcGIS Pro软件是否也可以批量导出符号用于其它地图…

Java-数据结构-排序-(一) (。・ω・。)

文本目录&#xff1a; ❄️一、排序的概念及引用&#xff1a; ➷ 排序的概念&#xff1a; ➷ 常见的排序算法&#xff1a; ❄️二、插入排序的实现&#xff1a; ➷ 1、直接插入排序&#xff1a; ☞ 直接插入排序的基本思想&#xff1a; ☞ 直接插入排序的实现&#xff1a; ▶…

UI自动化测试(python)Web端4.0

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

PyCharm与Anaconda超详细安装配置教程

1、安装Anaconda&#xff08;过程&#xff09;-CSDN博客 2.创建虚拟环境conda create -n pytorch20 python3.9并输入conda activate pytorch20进入 3.更改镜像源conda/pip(只添加三个pip源和conda源即可) 4.安装PyTorch&#xff08;CPU版&#xff09; 5.安装Pycharm并破解&…

使用 Anaconda 环境在Jupyter和PyCharm 中进行开发

目录 前言 一、在特定环境中使用jupyter 1. 列出所有环境 2. 激活环境 3. 进入 Jupyter Notebook 二、在特定环境中使用pycham 1. 打开 PyCharm 2. 打开设置 3. 配置项目解释器 4. 选择 Conda 环境 5. 应用设置 6. 安装所需库&#xff08;如果需要&#xff09; 总结 &#x1f3…