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

Spring Boot 动态数据源实操指南

在实际开发中,我们经常会遇到需要动态切换数据源的场景,比如多租户系统、读写分离、分库分表等。Spring Boot 提供了灵活的配置方式,结合 AbstractRoutingDataSource 可以轻松实现动态数据源切换。本文将带你一步步实现 Spring Boot 动态数据源的配置与使用。


一、动态数据源的原理

Spring Boot 的动态数据源核心原理是通过 AbstractRoutingDataSource 实现数据源的路由。AbstractRoutingDataSource 是一个抽象类,它允许我们根据当前的上下文(如线程局部变量)动态选择目标数据源。

核心流程:

  1. 定义多个数据源(如主库、从库)。
  2. 继承 AbstractRoutingDataSource,实现 determineCurrentLookupKey() 方法,返回当前线程需要使用的数据源标识。
  3. 通过 AOP 或手动切换的方式,动态设置数据源标识。

二、实现步骤

1. 创建 Spring Boot 项目

使用 Spring Initializr 创建一个 Spring Boot 项目,添加以下依赖:

  • Spring Web
  • Spring Data JPA
  • MySQL Driver
  • HikariCP(连接池)
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId></dependency>
</dependencies>

2. 配置多数据源

application.yml 中配置多个数据源,例如主库和从库:

spring:datasource:master:jdbc-url: jdbc:mysql://localhost:3306/master_dbusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driverslave:jdbc-url: jdbc:mysql://localhost:3306/slave_dbusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver

3. 创建数据源配置类

通过 Java 配置类加载多个数据源。

@Configuration
public class DataSourceConfig {@Bean(name = "masterDataSource")@ConfigurationProperties(prefix = "spring.datasource.master")public DataSource masterDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "slaveDataSource")@ConfigurationProperties(prefix = "spring.datasource.slave")public DataSource slaveDataSource() {return DataSourceBuilder.create().build();}
}

4. 实现动态数据源路由

创建 DynamicDataSource 类继承 AbstractRoutingDataSource,并实现 determineCurrentLookupKey() 方法。

public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSourceKey();}
}

5. 创建数据源上下文管理类

使用 ThreadLocal 保存当前线程的数据源标识。

public class DataSourceContextHolder {private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();public static void setDataSourceKey(String key) {contextHolder.set(key);}public static String getDataSourceKey() {return contextHolder.get();}public static void clearDataSourceKey() {contextHolder.remove();}
}

6. 配置动态数据源

将多个数据源注入到 DynamicDataSource 中。

@Configuration
public class DynamicDataSourceConfig {@Beanpublic DataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,@Qualifier("slaveDataSource") DataSource slaveDataSource) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("master", masterDataSource);targetDataSources.put("slave", slaveDataSource);DynamicDataSource dynamicDataSource = new DynamicDataSource();dynamicDataSource.setDefaultTargetDataSource(masterDataSource); // 默认数据源dynamicDataSource.setTargetDataSources(targetDataSources);return dynamicDataSource;}
}

7. 配置事务管理器

由于动态数据源的切换会影响事务管理,需要配置一个支持动态数据源的事务管理器。

@Bean
public PlatformTransactionManager transactionManager(DataSource dynamicDataSource) {return new DataSourceTransactionManager(dynamicDataSource);
}

8. 使用 AOP 动态切换数据源

通过 AOP 在方法执行前切换数据源。

@Aspect
@Component
public class DataSourceAspect {@Before("@annotation(com.example.demo.annotation.Master)")public void setMasterDataSource() {DataSourceContextHolder.setDataSourceKey("master");}@Before("@annotation(com.example.demo.annotation.Slave)")public void setSlaveDataSource() {DataSourceContextHolder.setDataSourceKey("slave");}@After("@annotation(com.example.demo.annotation.Master) || @annotation(com.example.demo.annotation.Slave)")public void clearDataSource() {DataSourceContextHolder.clearDataSourceKey();}
}

9. 定义注解

为了方便切换数据源,定义两个注解:@Master@Slave

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Master {
}@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Slave {
}

10. 测试动态数据源

在 Service 层使用注解切换数据源。

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Masterpublic void addUser(User user) {userRepository.save(user);}@Slavepublic List<User> getUsers() {return userRepository.findAll();}
}

三、总结

通过以上步骤,我们实现了一个简单的 Spring Boot 动态数据源切换功能。核心点包括:

  1. 使用 AbstractRoutingDataSource 实现数据源路由。
  2. 通过 ThreadLocal 管理当前线程的数据源标识。
  3. 使用 AOP 和注解简化数据源切换。

动态数据源切换是一个非常实用的功能,适用于多租户、读写分离等场景。希望本文能帮助你更好地理解和应用 Spring Boot 动态数据源技术!

相关文章:

Spring Boot 动态数据源实操指南

在实际开发中&#xff0c;我们经常会遇到需要动态切换数据源的场景&#xff0c;比如多租户系统、读写分离、分库分表等。Spring Boot 提供了灵活的配置方式&#xff0c;结合 AbstractRoutingDataSource 可以轻松实现动态数据源切换。本文将带你一步步实现 Spring Boot 动态数据…...

HBase高级技巧:解锁更强大的数据处理能力

HBase高级技巧&#xff1a;解锁更强大的数据处理能力 嘿&#xff0c;小伙伴们&#xff01;在掌握了HBase的基本操作之后&#xff0c;今天我们将深入探讨一些HBase的高级技巧。这些技巧将帮助你在面对复杂的数据处理需求时更加得心应手&#xff0c;进一步提升系统的性能和可靠性…...

【进阶】JVM篇

为什么学习jvm 1、面试的需要 学过java的程序员对jvm应该不陌生&#xff0c;程序员为什么要学习jvm呢&#xff1f;其实不懂jvm也可以照样写出优质的代码&#xff0c;但是不懂jvm会被大厂的面试官虐的体无完肤。 2、高级程序员需要了解 jvm作用 jvm负责把编译后的字节码转换…...

DeepSeek官方推荐的AI集成系统

DeepSeek模型虽然强大先进&#xff0c;但是模型相当于大脑&#xff0c;再聪明的大脑如果没有输入输出以及执行工具也白搭&#xff0c;所以需要有配套工具才能让模型发挥最大的作用。下面是一个典型AI Agent架构图&#xff0c;包含核心组件与数据流转关系&#xff1a; #mermaid-…...

【动态规划篇】:当回文串遇上动态规划--如何用二维DP“折叠”字符串?

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;动态规划篇–CSDN博客 文章目录 一.回文串类DP核心思想&#xff08;判断所有子串是否是回文…...

JENKINS(全面)

一.linux系统中JENKINS的安装 注意&#xff1a;安装jenkins需要安装jdk&#xff0c;而且具体版本的jenkins有相对应的jdk版本。可参考以下链接。 Redhat Jenkins 软件包https://pkg.jenkins.io/redhat-stable/https://pkg.jenkins.io/redhat-stable/https://pkg.jenkins.io/r…...

Promise详解大全:介绍、九个方法使用和区别、返回值详解

Promise的介绍 Promise是异步编程的一种解决方案&#xff0c;它的构造函数是同步执行的&#xff0c;then 方法是异步执行的&#xff0c;所以Promise创建后里面的函数会立即执行&#xff0c;构造函数中的resolve和reject只有第一次执行有效&#xff0c;&#xff0c;也就是说Pro…...

尚硅谷爬虫note004

一、urllib库 1. python自带&#xff0c;无需安装 # _*_ coding : utf-8 _*_ # Time : 2025/2/11 09:39 # Author : 20250206-里奥 # File : demo14_urllib # Project : PythonProject10-14#导入urllib.request import urllib.request#使用urllib获取百度首页源码 #1.定义一…...

Debezium系列之:时区转换器,时间戳字段转换到指定时区

Debezium系列之:时区转换器,时间戳字段转换到指定时区 示例:基本配置应用TimezoneConverter SMT的效果示例:高级配置配置选项当Debezium发出事件记录时,记录中的时间戳字段的时区值可能会有所不同,这取决于数据源的类型和配置。为了在数据处理管道和应用程序中保持数据一…...

ubuntu20.04声音设置

step1&#xff1a;打开pavucontrol&#xff0c;设置Configuration和Output Devices&#xff0c; 注意需要有HDMI / DisplayPort (plugged in)这个图标。如果没有&#xff0c;就先选择Configuration -> Digital Stereo (HDMI 7) Output (unplugged) (unvailable)&#xff0c;…...

如何设置Python爬虫的User-Agent?

在Python爬虫中设置User-Agent是模拟浏览器行为、避免被目标网站识别为爬虫的重要手段。User-Agent是一个HTTP请求头&#xff0c;用于标识客户端软件&#xff08;通常是浏览器&#xff09;的类型和版本信息。通过设置合适的User-Agent&#xff0c;可以提高爬虫的稳定性和成功率…...

深度学习框架探秘|TensorFlow:AI 世界的万能钥匙

在人工智能&#xff08;AI&#xff09;蓬勃发展的时代&#xff0c;各种强大的工具和框架如雨后春笋般涌现&#xff0c;而 TensorFlow 无疑是其中最耀眼的明星之一。它不仅被广泛应用于学术界的前沿研究&#xff0c;更是工业界实现 AI 落地的关键技术。今天&#xff0c;就让我们…...

C++:高度平衡二叉搜索树(AVLTree) [数据结构]

目录 一、AVL树 二、AVL树的理解 1.AVL树节点的定义 2.AVL树的插入 2.1更新平衡因子 3.AVL树的旋转 三、AVL的检查 四、完整代码实现 一、AVL树 AVL树是什么&#xff1f;我们对 map / multimap / set / multiset 进行了简单的介绍&#xff0c;可以发现&#xff0c;这几…...

建筑兔零基础自学python记录18|实战人脸识别项目——视频检测07

本次要学视频检测&#xff0c;我们先回顾一下图片的人脸检测建筑兔零基础自学python记录16|实战人脸识别项目——人脸检测05-CSDN博客 我们先把上文中代码复制出来&#xff0c;保留红框的部分。 ​ 然后我们来看一下源代码&#xff1a; import cv2 as cvdef face_detect_demo(…...

【MySQL数据库】Ubuntu下的mysql

目录 1&#xff0c;安装mysql数据库 2&#xff0c;mysql默认安装路径 3&#xff0c;my.cnf配置文件? 4&#xff0c;mysql运用的相关指令及说明 5&#xff0c;数据库、表的备份和恢复 mysql是一套给我们提供数据存取的&#xff0c;更加有利于管理数据的服务的网络程序。下…...

[MySQL#1] database概述 常见的操作指令 MySQL架构 存储引擎

#1024程序员节&#xff5c;征文# 目录 一. 数据库概念 0.连接服务器 1. 什么是数据库 口语中的数据库 为什么数据不直接以文件形式存储&#xff0c;而需要使用数据库呢&#xff1f; 总结 二. ??基础操作 三. 主流数据库 四. 基础知识 服务器&#xff0c;数据库&…...

1.从零开始学会Vue--{{基础指令}}

全新专栏带你快速掌握Vue2Vue3 1.插值表达式{{}} 插值表达式是一种Vue的模板语法 我们可以用插值表达式渲染出Vue提供的数据 1.作用&#xff1a;利用表达式进行插值&#xff0c;渲染到页面中 表达式&#xff1a;是可以被求值的代码&#xff0c;JS引擎会将其计算出一个结果 …...

VS2022中.Net Api + Vue 从创建到发布到IIS

VS2022中.Net Api Vue 从创建到发布到IIS 前言一、先决条件二、创建项目三、运行项目四、增加API五、发布到IIS六、设置Vue的发布 前言 最近从VS2019 升级到了VS2022,终于可以使用官方的.Net Vue 组合了,但是使用过程中还是有很多问题,这里记录一下. 一、先决条件 Visual …...

RFID技术在制造环节的应用与价值

在现代制造业中&#xff0c;信息化和智能化已经成为企业提升竞争力的重要手段。RFID技术因其非接触式、远距离和高效识别的特点&#xff0c;广泛应用于生产的多个环节。本文将详细解读生产过程中RFID的关键应用场景&#xff0c;并结合实际案例&#xff0c;展示其为制造业带来的…...

(前端基础)HTML(一)

前提 W3C:World Wide Web Consortium&#xff08;万维网联盟&#xff09; Web技术领域最权威和具有影响力的国际中立性技术标准机构 其中标准包括&#xff1a;机构化标准语言&#xff08;HTML、XML&#xff09; 表现标准语言&#xff08;CSS&#xff09; 行为标准&#xf…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...