【mybatis-plus进阶】多租户场景中多数据源自定义来源dynamic-datasource实现

Springboot+mybatis-plus+dynamic-datasource+Druid 多租户场景中多数据源自定义来源dynamic-datasource实现

文章目录

  • Springboot+mybatis-plus+dynamic-datasource+Druid 多租户场景中多数据源自定义来源dynamic-datasource实现
  • 0.前言
    • 1. 作者提供了接口
    • 2. 基于此接口的抽象类实现
    • 自定义负载均衡策略
    • 如何自定义
    • 多数据源懒启动配置
  • 3. 参考资料

0.前言

我们低代码平台是支持多租户的模式,用户在平台上配置了多数据源后,数据源会持久化到低代码的数据库中。多租户场景中多数据源自定义来源 是从数据库中通过查询数据源配置信息表,获取到数据库的链接信息和配置信息,然后利用 dynamic-datasource创建多数据源对象注入到容器里。
在这里插入图片描述

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

1. 作者提供了接口

在这里插入图片描述

2. 基于此接口的抽象类实现

 @Beanpublic DynamicDataSourceProvider jdbcDynamicDatasourceProvider(DynamicDataSourceProperties properties) {// 获取Primary动态数据源Map<String, DataSourceProperty> datasourceMap = properties.getDatasource();DataSourceProperty masterDsProperty = datasourceMap.get(properties.getPrimary());// 从项目配置文件里配置的主数据源中DB加载要多租户的数据源。我们主要用在低代码场景return new AbstractJdbcDataSourceProvider(masterDsProperty.getDriverClassName(),masterDsProperty.getUrl(), masterDsProperty.getUsername(), masterDsProperty.getPassword()) {@Overrideprotected Map<String, DataSourceProperty> executeStmt(Statement statement) {Map<String, DataSourceProperty> dataSourcePropertiesMap = null;ResultSet rs = null;try {dataSourcePropertiesMap = new HashMap<>();// DbConstant.DS_DB_SQL 为查询数据库中配置的多租户的数据源配置信息的SQL如// "SELECT * FROM DATABASE_CONFIG "rs = statement.executeQuery(DbConstant.DS_DB_SQL);while (rs.next()) {DataSourceProperty property = new DataSourceProperty();String databaseCode = rs.getString(DbConstant.DatabaseConfigField.DATABASE_CODE);property.setDriverClassName(rs.getString(DbConstant.DatabaseConfigField.DRIVER_CLASS));property.setUrl(rs.getString(DbConstant.DatabaseConfigField.DATABASE_URL));property.setUsername(rs.getString(DbConstant.DatabaseConfigField.USER_NAME));property.setPassword(AESUtil.decrypt(rs.getString(DbConstant.DatabaseConfigField.USER_PASSWORD)));property.setLazy(DS_DATASOURCE_LAZY);// 设置Druid配置String druidConfig = rs.getString(DbConstant.DatabaseConfigField.DRUID_CONFIG);property.setDruid(getDruidConfig(druidConfig));dataSourcePropertiesMap.put(databaseCode, property);}} catch (SQLException e) {log.error("查询DB数据源配置异常", e);} finally {try {if (rs != null) {rs.close();}} catch (SQLException e) {log.error("数据库ResultSet资源释放异常", e);}try {statement.close();} catch (SQLException e) {log.error("数据库Statement资源释放异常", e);}}log.info(">>>初始化加载DB库中数据源完成");return dataSourcePropertiesMap;}};}

自定义负载均衡策略

如下图slave组下有三个数据源,当用户使用slave切换数据源时会使用负载均衡算法。

系统自带了两个负载均衡算法

LoadBalanceDynamicDataSourceStrategy 轮询,是默认的。
RandomDynamicDataSourceStrategy 随机的。

spring:datasource:dynamic:datasource:master:username: sapassword: ""url: jdbc:h2:mem:testdriver-class-name: org.h2.Driverschema: db/schema.sqlslave_1:username: sapassword: ""url: jdbc:h2:mem:testdriver-class-name: org.h2.Driverslave_2:username: sapassword: ""url: jdbc:h2:mem:testdriver-class-name: org.h2.Driverslave_3:username: sapassword: ""url: jdbc:h2:mem:testdriver-class-name: org.h2.Driverstrategy: com.baomidou.dynamic.datasource.strategy.LoadBalanceDynamicDataSourceStrategy

如何自定义

如果默认的两个都不能满足要求,可以参考源码自定义。 暂时只能全局更改。

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import javax.sql.DataSource;public class RandomDynamicDataSourceStrategy implements DynamicDataSourceStrategy {public RandomDynamicDataSourceStrategy() {}public DataSource determineDataSource(List<DataSource> dataSources) {return (DataSource)dataSources.get(ThreadLocalRandom.current().nextInt(dataSources.size()));}
}

多数据源懒启动配置

懒启动:连接池创建出来后并不会立即初始化连接池,等需要使用connection的时候再初始化。

暂时只支持Druid和HikariCp和BeeCp连接池。

主要场景可能适合于数据源很多,又不需要启动立即初始化的情况,可以减少系统启动时间。

缺点在于,如果参数配置有误,则启动的时候不知道,初始化的时候失败,可能一直抛异常。

配置使用

spring:datasource:dynamic:primary: master #设置默认的数据源或者数据源组,默认值即为masterstrict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.lazy: true #默认false非懒启动,系统加载到数据源立即初始化连接池datasource:master:url: jdbc:mysql://xx.xx.xx.xx:3306/dynamicusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverlazy: true #表示这个数据源懒启动db1:url: jdbc:mysql://xx.xx.xx.xx:3307/dynamicusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverdb2:url: jdbc:mysql://xx.xx.xx.xx:3307/dynamicusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driver

3. 参考资料

从3.4.0开始,可以注入多个DynamicDataSourceProvider的Bean以实现同时从多个不同来源加载数据源,注意同名会被覆盖。

  1. dynamic-datasource GitHub 仓库 ↗:dynamic-datasource 的官方 GitHub 仓库,包含源代码、文档和示例等资源。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

macOS通过钥匙串访问找回WiFi密码

如果您忘记了Mac电脑上的WiFi密码&#xff0c;可以通过钥匙串访问来找回它。具体步骤如下&#xff1a; 1.打开Mac电脑的“启动台”&#xff0c;然后在其他文件中找到“钥匙串访问”。 2.运行“钥匙串访问”应用程序&#xff0c;点击左侧的“系统”&#xff0c;然后在右侧找到…

Gin学习记录3——模版与渲染

模版与渲染 一. 返回二. 模版2.1 基础模版2.2 同名模版2.3 模版继承2.4 模版语法 一. 返回 如果只是想返回数据&#xff0c;可以使用以下函数&#xff1a; func (c *Context) JSON(code int, obj any) func (c *Context) JSONP(code int, obj any) func (c *Context) String(…

Shotcut for Mac:一款强大而易于使用的视频编辑器

随着数码相机的普及&#xff0c;视频编辑已成为我们日常生活的一部分。对于许多专业和非专业用户来说&#xff0c;找到一个易于使用且功能强大的视频编辑器是至关重要的。今天&#xff0c;我们将向您介绍Shotcut——一款专为Mac用户设计的强大视频编辑器。 什么是Shotcut&…

POI基于Excel模板导出数据

1、基于模板导出列表数据 1.1、需求 注意&#xff1a;使用附件的形式下载&#xff0c;前端访问必须通过window.open(),否则附件可能无法下载。 按照以下样式导出excel 1.2、思路 首先准备一个excel模板&#xff0c;这个模板把复杂的样式和固定的内容先准备好并且放入到项…

佳作导读 | 《C++ Core Guidelines》

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 佳作导读 | 《C Core Guidelines》 《C Core Guidelines》由Bjarne Stroustrup和Herb Sutter等共同编写关于使用C编程语言的指南&#xff1b;旨在提供关于如何使用C进…

在Ubuntu上安装CUDA和cuDNN以及验证安装步骤

在Ubuntu上安装CUDA和cuDNN以及验证安装步骤 本教程详细介绍了如何在Ubuntu操作系统上安装CUDA&#xff08;NVIDIA的并行计算平台&#xff09;和cuDNN&#xff08;深度神经网络库&#xff09;&#xff0c;以及如何验证安装是否成功。通过按照这些步骤操作&#xff0c;您将能够…

小黑受到了未来的焦虑,周四继续参加团跑活动仰山跑,跑奥森的坡,越跑越上瘾更加热爱生活的leetcode之旅:LCR 008. 长度最小的子数组

小黑代码1 class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:# 数组长度n len(nums)# 双指针head 0tail 0# 中间变量sum_ 0# 结果变量res n1# 开始双指针迭代while tail < n:sum_ nums[tail]tail 1while sum_ > target:if tail…

0010Java程序设计-springboot+vue影院售票系统设计与实现

摘 要目 录系统实现开发环境 摘 要 看电影已经成为了人们生活中不可缺少的一部分&#xff0c;电影院售票及管理系统是电影院的日常管理及售票任务的核心&#xff0c; 在电影院中&#xff0c; 工作人员并非只是放映电影&#xff0c; 还有诸如票房统计、影片放映、影片场次安排、…

动态规划:路径和子数组问题(C++)

动态规划&#xff1a;路径和子数组问题 路径问题1.不同路径&#xff08;中等&#xff09;2.不同路径II&#xff08;中等&#xff09;3.下降路径最⼩和&#xff08;中等&#xff09;4.地下城游戏&#xff08;困难&#xff09; 子数组问题1.最大子数组和&#xff08;中等&#xf…

一篇文章教会你SpringMVC

目录 1.什么是SpringMVC 2.SpringMVC工作流程 3.SpringMVC核心组件 4.SpringMVC的配置流程 4.1导入POM依赖 4.2在WEB-INF下添加springmvc-servlet.xml(spring-mvc.xml) 4.3 修改web.xml 创建一个Controller用来存放web层的方法和内容 创建一个前端页面用来做测试展示 前言…

04 Linux补充|C/C++

目录 Linux补充 C语⾔ C语言中puts和printf的区别&#xff1f; Linux补充 (1)ubuntu安装ssh服务端openssh-server命令&#xff1a; ubuntu安装后默认只有ssh客户端&#xff0c;只能去连其它ssh服务器&#xff1b;其它客户端想要连接这个ubuntu系统&#xff0c;需要安装部署…

进制转换(二进制、八进制、十六进制、十进制)

一、进制表示 二进制&#xff1a;每一位只有两种符号表示 -> 0,1 例如 (101011)₂&#xff0c;也可写作101011B&#xff0c;其中B是Binary英文的缩写。八进制&#xff1a; 每一位有8种符号表示(0~7)&#xff0c;例如(1652)₈&#xff0c;也可写作1652O&#xff0c;其中O是O…

STL常用容器 (C++核心基础教程之STL容器详解)String的API

在C的标准模板库&#xff08;STL&#xff09;中&#xff0c;有多种容器可供使用。以下是一些常见的容器类型&#xff1a; 序列容器&#xff08;Sequential Containers&#xff09;&#xff1a; std::vector&#xff1a;动态数组&#xff0c;支持快速随机访问。 std::list&…

CS420 课程笔记 P7 - 虚拟内存 多级指针寻址

文章目录 IntroPointersMemory leaksPointer pathPointer scanningExample! Intro 上节课我们学习了静态地址&#xff0c;这节课我们将着手关注动态地址&#xff0c;我们需要了解一个叫做指针的东西 Pointers 简单地说&#xff0c;指针是对象之间的单向连接 Pointers are co…

vue集成mars3d后,basemaps加不上去

首先&#xff1a; <template> <div id"centerDiv" class"mapcontainer"> <mars-map :url"configUrl" οnlοad"onMapload" /> </div> </template> <script> import MarsMap from ../component…

C到C++的升级

C和C的关系 C继承了所有C语言的特性&#xff1b;C在C的基础上提供了更多的语法和特性&#xff0c;C语言去除了一些C语言的不好的特性。C的设计目标是运行效率与开发效率的统一。 变化一&#xff1a;所有变量都可以在使用时定义 C中更强调语言的实用性&#xff0c;所有的变量…

解决centos离线安装cmake找不到OpenSSL问题

安装方法&#xff1a;见另外一篇文章 https://blog.csdn.net/zhongxj183/article/details/118488629 按照文章下载了离线gcc 和OpenSSL&#xff0c;以及在cmake官网下载了最新版 cmake-3.27.4.tar.gz 顺利安装gcc 和OpenSSL 但执行编译cmake时&#xff0c;报错找不到OpenSSL…

【python】读取.dat格式文件

import binascii# 打开二进制文件以只读二进制模式 with open(EXCEL/文件.dat, rb) as file:binary_data file.read()print(binary_data)# 将二进制数据转换为十六进制字符串 hex_data binascii.hexlify(binary_data).decode(utf-8) # binary_data 现在包含了文件的二进制内容…

计算机图形学线性代数相关概念

Transformation&#xff08;2D-Model&#xff09; Scale(缩放) [ x ′ y ′ ] [ s 0 0 s ] [ x y ] (等比例缩放) \left[ \begin{matrix} x \\ y \end{matrix} \right] \left[ \begin{matrix} s & 0 \\ 0 & s \end{matrix} \right] \left[ \begin{matrix} x \\ y \en…

页面页脚部分CSS分享

先看效果&#xff1a; CSS部分&#xff1a;&#xff08;查看更多&#xff09; <style>body {display: grid;grid-template-rows: 1fr 10rem auto;grid-template-areas: "main" "." "footer";overflow-x: hidden;background: #F5F7FA;min…