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

SpringBoot轻松实现多数据源切换

一.需求背景

项目需要实现在多个数据源之间读写数据,例如在 A 数据源和 B 数据源读取数据,然后在 C 数据源写入数据 或者 部分业务数据从 A 数据源中读取、部分从B数据源中读取诸如此类需求。本文将简单模拟在SpringBoot项目中实现不同数据源之间读取数据。

二.技术概述

dynamic-datasource 是一个开源的 SpringBoot 多数据源启动器,提供了丰富的功能,使用者只需完成基本的数据源配置,配合使用@DS注解即可轻松实现多数据源之间的切换。其支持 Jdk 1.7+, SpringBoot 1.5.x 2.x.x 3.x.x。JPA用户不建议使用,JPA自带事务,无法连续切库。

以下特性和约定摘录自官方文档:dynamic-datasource

  • 特性

    • 支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。

    • 支持数据库敏感配置信息 加密(可自定义) ENC()。

    • 支持每个数据库独立初始化表结构schema和数据库database。

    • 支持无数据源启动,支持懒加载数据源(需要的时候再创建连接)。

    • 支持 自定义注解 ,需继承DS(3.2.0+)。

    • 提供并简化对Druid,HikariCp,BeeCp,Dbcp2的快速集成。

    • 提供对Mybatis-Plus,Quartz,ShardingJdbc,P6sy,Jndi等组件的集成方案。

    • 提供 自定义数据源来源 方案(如全从数据库加载)。

    • 提供项目启动后 动态增加移除数据源 方案。

    • 提供Mybatis环境下的 纯读写分离 方案。

    • 提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。

    • 支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)

    • 提供 基于seata的分布式事务方案

    • 提供 本地多数据源事务方案。

  • 约定

    1. 本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
    2. 配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。
    3. 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。、
    4. 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。
    5. 代码块里主动切换 > 方法上的注解优 > 类上注解(就近原则)
    6. DS支持继承抽象类上的DS,支持继承接口上的DS。

:官网文档只有基础篇可免费查阅,其他内容查阅需付费29.9¥,因此如果基础篇所讲解功能无法满足需求(业务场景比较复杂)且不愿付费请勿使用本框架!

三.编码实现

业务说明:从A数据源查询出学生数据同时从B数据源查询出教师数据。

技术选型:SpringBoot 2.7.6 + MyBatis-Plus 3.5.4 + MySQL 8.0

1)引入Maven坐标

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.2</version>
</dependency>

2)创建模拟数据库表,

# A 数据源
create DATABASE testA;
use testA;
CREATE TABLE student(
id int,
username VARCHAR(12)
);# B 数据源
create DATABASE testB;
use testB;
CREATE TABLE teacher(
id int,
username VARCHAR(12)
);

3)在yml文件中配置数据源

spring:datasource:dynamic:primary: testA  #设置默认的数据源或者数据源组,默认值即为masterstrict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源datasource:testA:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/testAusername: rootpassword: roottestB:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/testBusername: rootpassword: root

4)可以用MyBatis-X插件快速生成项目骨架。

在这里插入图片描述

5)使用@DS注解在mapper文件中指定数据源。注意,数据源名称需要与yml配置中的一致。

// 指定学生表的数据源为testA
@DS("testA")
public interface StudentMapper extends BaseMapper<Student> {
}// 指定教师表的数据源为testB
@DS("testB")
public interface TeacherMapper extends BaseMapper<Teacher> {
}

5)创建测试类进行测试

@SpringBootTest
public class MultipleDataSourceTest {@Resourceprivate StudentService studentService;@Resourceprivate TeacherService teacherService;@Testvoid testSelect() {System.out.println("====== 学生表数据 ======");for (Student student : studentService.list()) {System.out.println(">>> " + student);}System.out.println("====== 教师表数据 ======");for (Teacher teacher : teacherService.list()) {System.out.println(">>> " + teacher);}}
}

6)相关执行日志查看,可以通过日志看到已经成功加载两个数据源并且指定默认数据源为[testA],同时我们所查询的数据也能正常出来。

INFO 312 --- [main] com.zaxxer.hikari.HikariDataSource: testA - Starting...
INFO 312 --- [main] com.zaxxer.hikari.HikariDataSource: testA - Start completed.
INFO 312 --- [main] com.zaxxer.hikari.HikariDataSource: testB - Starting...
INFO 312 --- [main] com.zaxxer.hikari.HikariDataSource: testB - Start completed.
INFO 312 --- [main] c.b.d.d.DynamicRoutingDataSource: dynamic-datasource - add a datasource named [testB] success
INFO 312 --- [main] c.b.d.d.DynamicRoutingDataSource: dynamic-datasource - add a datasource named [testA] success
INFO 312 --- [main] c.b.d.d.DynamicRoutingDataSource: dynamic-datasource initial loaded [2] datasource,primary datasource named [testA]
====== 学生表数据 ======
>>> Student(id=1, username=学生1)
>>> Student(id=2, username=学生2)
>>> Student(id=3, username=学生3)
>>> Student(id=4, username=学生4)
>>> Student(id=5, username=学生5)
====== 教师表数据 ======
>>> Teacher(id=1, username=教师1)
>>> Teacher(id=2, username=教师2)
>>> Teacher(id=3, username=教师3)
>>> Teacher(id=4, username=教师4)
>>> Teacher(id=5, username=教师5)
INFO 312 --- [ionShutdownHook] c.b.d.d.DynamicRoutingDataSource: dynamic-datasource start closing ....
INFO 312 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource: testB - Shutdown initiated...
INFO 312 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource: testB - Shutdown completed.
INFO 312 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource: testA - Shutdown initiated...
INFO 312 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource: testA - Shutdown completed.
INFO 312 --- [ionShutdownHook] c.b.d.d.DynamicRoutingDataSource: dynamic-datasource all closed success,bye

四.补充说明

以上示例可以完成基本的多数据源切换需求,对于一些复杂场景,由于官方文档付费,请根据需要使用。例如:

  • 在需要切换数据源的代码最外层加上了事务注解@Transactional将会导致数据源切换失效,上述代码加上注解运行将报错(由于无法切换数据源,将使用默认数据源,如果默认数据源中没有对应的表将报错),在网上检索发现通过添加官方提供的@DSTransactional即可实现事务下数据源切换:

        @Test@Transactionalvoid testSelect() {System.out.println("====== 学生表数据 ======");for (Student student : studentService.list()) {System.out.println(">>> " + student);}System.out.println("====== 教师表数据 ======");for (Teacher teacher : teacherService.list()) {System.out.println(">>> " + teacher);}}
    
  • 在多线程情况下,如果使用编码方式实现数据源切换也将导致问题,需要进行一些其他处理。

最后,补充说明想表达的由于官网文档是付费的,不付费的话许多问题只能搜索寻找解决方法比较麻烦,因此,请根据自身业务情况选择使用本框架或其他框架。

相关文章:

SpringBoot轻松实现多数据源切换

一.需求背景 项目需要实现在多个数据源之间读写数据&#xff0c;例如在 A 数据源和 B 数据源读取数据&#xff0c;然后在 C 数据源写入数据 或者 部分业务数据从 A 数据源中读取、部分从B数据源中读取诸如此类需求。本文将简单模拟在SpringBoot项目中实现不同数据源之间读取数…...

Qt 5 当类的信号函数和成员函数,函数名相同时,连接信号和槽的写法。

前言&#xff1a;因为项目需要&#xff0c;软件要在windows7上运行&#xff0c;然后项目目前是qt6写的&#xff0c;然后搜索资料&#xff0c;需要qt5.15.2或之前的版本才能在win7上运行&#xff0c;于是下载了qt5.15.2&#xff0c;将qt6的代码在qt5编译时&#xff0c;很多错误&…...

Vuex 介绍及示例

Vuex 是 Vue.js 的一个状态管理模式和库&#xff0c;用于管理 Vue 应用中的全局状态。它是专门为 Vue.js 应用设计的&#xff0c;充分利用了 Vue 的细粒度响应系统来高效地更新状态。以下是对 Vuex 的一些介绍和它的基本使用方法&#xff1a; 主要概念 State&#xff08;状态&…...

【elementui】记录如何重命名elementui组件名称

在main.js中&#xff0c;就是引入elementui的文件中 import ElementUI from element-ui import { Tree } from element-uiVue.use(ElementUI) Vue.component(el-tree-rename, Tree)...

MySQL面试篇章—MySQL锁机制

文章目录 MySQL的锁机制表级锁 & 行级锁排它锁和共享锁InnoDB行级锁行级锁间隙锁意向共享锁和意向排它锁 InnoDB表级锁死锁锁的优化建议MVCC多版本并发控制MyISAM表级锁表级锁并发插入优化锁调度优化 MySQL的锁机制 表级锁 & 行级锁 表级锁&#xff1a;对整张表加锁&…...

OAK相机支持的图像传感器有哪些?

相机支持的传感器 在 RVC2 上&#xff0c;固件必须具有传感器配置才能支持给定的相机传感器。目前&#xff0c;我们支持下面列出的相机传感器的开箱即用&#xff08;固件中&#xff09;传感器配置。 名称 分辨率 传感器类型 尺寸 最大 帧率 IMX378 40563040 彩色 1/2.…...

网络安全威胁情报是什么,它对代工生产(OEM)意味着什么?

随着汽车数字环境的不断变化&#xff0c;网络安全基础设施及其面临的威胁也日趋复杂。 为了更好地识别、理解并最终预防这些风险&#xff0c;网络安全威胁情报&#xff08;CTI&#xff09;的管理应是一个综合多方面的过程。 以下是CTI对OEM的意义&#xff0c;以及如何利用网络…...

【基础篇】Docker 架构与组件 TWO

嗨&#xff0c;小伙伴们&#xff01;我是小竹笋&#xff0c;一名热爱创作的工程师。上一篇我们聊了聊 Docker 的历史与发展、与虚拟机的对比以及它在行业中的应用。今天&#xff0c;让我们更进一步&#xff0c;深入探讨 Docker 的架构与关键组件。 欢迎订阅公众号&#xff1a;…...

03。正式拿捏ArkTS语言第一天

1, 打印日志命令 &#xff1a; console.log() 2, 三种基本数据类型&#xff1a; number 数字类型 &#xff08;数字&#xff09; string 字符串类型&#xff08;例如&#xff1a;“我是字符串”&#xff09; boolean 布尔类型 (true 或者 false) ***…...

【PyTorch][chapter 27][李宏毅深度学习][attention-3]

前言&#xff1a; 前面重点讲了self-attention, mulitHead self-attention. 目录&#xff1a; self-attention positional Encoding 语音处理例子 跟CNN区别 跟 RNN 区别 一 self-attention 回顾 优点 1 解决了长序列依赖问题 2 并行计算 缺点 1 开销变大 增加了 Q…...

java-数据结构与算法-02-数据结构-05-栈

文章目录 1. 栈1. 概述2. 链表实现3. 数组实现4. 应用 2. 习题E01. 有效的括号-Leetcode 20E02. 后缀表达式求值-Leetcode 120E03. 中缀表达式转后缀E04. 双栈模拟队列-Leetcode 232E05. 单队列模拟栈-Leetcode 225 1. 栈 1. 概述 计算机科学中&#xff0c;stack 是一种线性的…...

Python 管理依赖包(pip, virtualenv)

在Python编程中&#xff0c;管理依赖包是开发工作的重要组成部分。正确管理依赖包可以确保代码在不同环境中的一致性和可移植性&#xff0c;避免版本冲突和依赖地狱等问题。Python中常用的依赖包管理工具包括pip和virtualenv。 一、pip pip是Python官方推荐的包管理工具&…...

Bigdecimal 导出为excel时显示未0E-10,不是0,怎么解决

在使用 ​​BigDecimal​​​ 导出到 Excel 时&#xff0c;如果遇到显示为 ​​0E-10​​​ 而不是 ​​0​​​ 的问题&#xff0c;这通常是因为 ​​BigDecimal​​​ 对象的精度问题。​​0E-10​​​ 表示的是 ​​0​​​ 乘以 10 的 -10 次方&#xff0c;这在数学上等同于…...

springboot项目从jdk8升级为jdk17过程记录

背景&#xff1a;公司有升级项目jdk的规划&#xff0c;计划从jdk8升级到jdk11 开始 首先配置本地的java_home 参考文档&#xff1a;Mac环境下切换JDK版本及不同的maven-CSDN博客 将pom.xml中jdk1.8相关的版本全部改为jdk17&#xff0c;主要是maven编译插件之类的&#xff0c…...

list、tuple、set和dict传参机制

1、list、tuple、set和dict传参机制 # -------------list------------- def f1(my_list):print(f"②f1()my_list:{my_list} 地址是&#xff1a;{id(my_list)}") # ["tom","mary","hsp"] 0x1122my_list[0]"jack"print(f&quo…...

Redis快速入门基础

Redis入门 Redis是一个基于内存的 key-value 结构数据库。mysql是二维表的接口数据库 优点&#xff1a; 基于内存存储&#xff0c;读写性能高 适合存储热点数据(热点商品、资讯、新闻) 企业应用广泛 官网:https://redis.io 中文网:https://www.redis.net.cn/ Redis下载与…...

python基础介绍

这次的专题是关于python的知识点&#xff0c;加油&#xff01; 文章目录 1 什么是计算机(1.1 哪些可以称为计算机&#xff1f;&#xff08;以下&#xff09;(1.2 计算机可以完成的工作有哪些&#xff1f;(1.3 一台计算机由什么构成&#xff1f; 2. 什么是编程&#xff08;2.1 编…...

SSRF中伪协议学习

SSRF常用的伪协议 file:// 从文件系统中获取文件内容,如file:///etc/passwd dict:// 字典服务协议,访问字典资源,如 dict:///ip:6739/info: ftp:// 可用于网络端口扫描 sftp:// SSH文件传输协议或安全文件传输协议 ldap://轻量级目录访问协议 tftp:// 简单文件传输协议 gopher…...

Java | Leetcode Java题解之第284题窥视迭代器

题目&#xff1a; 题解&#xff1a; class PeekingIterator<E> implements Iterator<E> {private Iterator<E> iterator;private E nextElement;public PeekingIterator(Iterator<E> iterator) {this.iterator iterator;nextElement iterator.next(…...

哈尔滨等保定级的常见问题

一、哈尔滨等保测评定级标准理解问题 哈尔滨等保测评如何确定信息系统的安全保护等级&#xff1f; 信息系统的安全保护等级应根据其在国家安全、经济建设、社会生活中的重要程度&#xff0c;以及一旦遭到破坏后对国家安全、社会秩序、公共利益以及公民、法人和其他组织的合法权…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...