项目应用多数据源动态切换(动态切换数据库连接)

news2024/11/20 15:39:17

文章目录

  • 前言
  • 准备阶段
  • 具体配置
  • 功能展示
    • 注解方式切换数据源
    • 代码方式切换数据源
      • 优化方式
  • 动态添加删除数据源
  • 事务问题
  • 参考文章

前言

最近公司的权限项目要实现多租户的功能,于是就要做数据隔离以确保每个租户的数据的安全性,但是项目中也要动态的提供能够添加租户和删除租户的功能,这就需要动态的添加数据源(数据库连接地址。。),于是就去找了找相关的资料,今天就整理总结一下如何实现这个功能。

准备阶段

项目的框架是springboot+JDBC,那么多数据源这个也有框架,使用的是dynamic-datasource这个框架,这个框架和mybatis-plus是同一家的,这里使用的是4.2.0版本,这个版本官方推荐使用的:官方地址

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

具体配置

这里是基础的配置演示,这里配置了两个数据源,分别是master和slave1,配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。当然如果没有这种分组的需要就不需要。同时这个 primary: master #设置默认的数据源或者数据源组,默认值即为master这个必须要设置,因为当你的一些方法或者类上没有标识使用那个数据源去执行SQL时会执行这个默认的数据源,在多说一句就是这个框架支持一主多从,多主多从这些配置,同时如果使用了分组的配置,分组中还有相应的负载均衡的策略去访问这个分组下的数据库。
在这里插入图片描述

spring:
  datasource:
    #dynamic开始多数据源配置
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      datasource:
        master:  # 数据源的名字:master
          username: root
          password: guyanshuang.
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql:///test1
        slave1:   # 数据源的名字:slave_1
          username: root
          password: guyanshuang.
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql:///test2

功能展示

注解方式切换数据源

框架提供的 @DS("数据源名称")注解可以帮助我们实现切换数据源的效果具体使用。
这是标记在方法上的,同时也可以标记到类上,那么如果方法和类都有标记注解,那么在调用标记注解的方法时,有限使用方法上注解标记的数据源。当然这种方式并不动态,因为上面说到了还要支持添加数据源的方式,那么这种方式肯定不行。
在这里插入图片描述
在这里插入图片描述

代码方式切换数据源

使用这种方式切换数据源才能算是动态的实现我上面提到的效果。
下面这两行代码就是关键,这是框架提供的方法,直接放到我们的业务代码之前即可。当然这种方式还是太繁琐了因为这两行代码的重复性太高了,作为一个程序员肯定不能做一个简单的CP工程师。

		//清除当前线程的数据源信息
		
        DynamicDataSourceContextHolder.clear();
        //切换到对应poolName(数据源名称)的数据源
        DynamicDataSourceContextHolder.push("slave_1");

同一个方法来回切换数据源也不必担心,这是线程级别的,不会相互影响
在这里插入图片描述

优化方式

既然这两行代码要在执行我们的业务代码前那么就写一个拦截器在请求进来前将这两行代码给执行了不就解决了我们重复的问题嘛。spring提供的一个拦截器HandlerInterceptor 接口

public class MyConfig implements HandlerInterceptor {
    /**
     * 请求处理程序(controller)执行之前调用。
     * @param request current HTTP request
     * @param response current HTTP response
     * @param handler chosen handler to execute, for type and/or instance evaluation
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        DynamicDataSourceContextHolder.clear();
        //切换到对应poolName的数据源
        DynamicDataSourceContextHolder.push("slave_1");
        return true;
    }
}

这样就做到了动态切换并且把切换的这个操作封装起来了
在这里插入图片描述

动态添加删除数据源

使用代码配置这个数据源,代码中提供的是添加的数据源操作,移除也很简单,根据数据源名称移除ds.removeDataSource(poolName);

    public void test3(){
        // 为DataSourceProperty提供相应的数据源配置信息
        DataSourceProperty dataSourceProperty=new DataSourceProperty();
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;

        DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
        // PoolName就是我们yaml配置中说的数据源名称
        ds.addDataSource("PoolName", dataSource);
    }

DataSourceProperty类就是我们在配置文件中配置的datasource相关的信息,可以看一下这个类的内部
在这里插入图片描述

在这里插入图片描述

事务问题

嵌套数据源的service中,如果操作了多个数据源,不能在最外层加上@Transaction开启事务,否则切换数据源不生效,因为这属于分布式事务了,需要用seata方案解决,如果是单个数据源(不需要切换数据源)可以用@Transaction开启事务,保证每个数据源自己的完整性。使用@Transaction注解开启的事务传播机制是required,如果需要每一个子service的事务生效就需要使用require_new,但是这又涉及到一个问题就是如果父service中的事务回滚并不会影响子service的事务回滚,所以需要使用seata。
框架也提供了一个@DSTransactional注解,只要@DSTransactional注解下任一环节发生异常,则全局多数据源事务回滚。但是@DSTransactional和@Transaction不可以混用

参考文章

入门推荐

深挖底层

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

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

相关文章

Unity性能优化分析篇

性能优化是游戏项目开发中一个重要环节。游戏帧率过低&#xff0c;手机发烫&#xff0c; 包体太大&#xff0c;低端机上跑不起来等, 这些都需要来做优化&#xff0c;不管过去&#xff0c;现在&#xff0c;未来&#xff0c;性能优化都是永恒的话题。 而性能优化首先要掌握的是性…

对话金山云高级副总裁刘涛 | 做大模型公司的助力者

“ AIGC的应用化阶段将很快到来&#xff1b;AGI&#xff0c;已步入助手阶段。” 口述 | 刘涛 整理 | 梦婕&云舒 出品&#xff5c;极新 在10月的最后一天&#xff0c;极新有幸采访到了金山云高级副总裁刘涛。我们深入探讨了“云计算逐鹿 AIGC”的话题。作为中国公有云互…

Opentracing概念介绍——Span

文章首发公众号&#xff1a;海天二路搬砖工 引言 作为分布式跟踪系统的标准化API&#xff0c;OpenTracing提供了一种通用的方式来追踪和分析分布式系统中的请求和操作。 在Opentracing中&#xff0c;Span是基本的跟踪单元&#xff0c;用于描述在分布式系统中的一个操作或事件…

csdn2023必看系列:最牛最全面的JMeter实现接口自动化测试教程

【文章末尾给大家留下了大量的福利哦】 一、JMETER的环境搭建 参考&#xff1a;https://www.cnblogs.com/qmfsun/p/4902534.html 二、JMETER的汉化 临时汉化方法&#xff1a;打开jmeter&#xff0c;options-->choose language-->选择语言 可以根据自己的需要选择简体…

【Python小程序】浮点矩阵加减法

一、内容简介 本文使用Python编写程序&#xff0c;实现2个m * n矩阵的加、减法。具体过程如下&#xff1a; 给定两个m*n矩阵A和B&#xff0c;返回A与B的和或差。 二、求解方法 将两个矩阵对应位置上的元素相加。 三、Python代码 import numpy as np# 用户输入两个矩阵的维…

Leetcode—67.二进制求和【简单】

2023每日刷题&#xff08;二十八&#xff09; Leetcode—67.二进制求和 实现代码 void reverse(char *a, int len) {for(int i 0; i < len / 2; i) {char tmp a[i];a[i] a[len - 1 - i];a[len - 1 - i] tmp;} }char* addBinary(char* a, char* b) {int len1 strlen(a…

微信小程序:仅前端实现对象数组的模糊查询

效果 核心代码 //对数组进行过滤&#xff0c;返回数组中每一想满足name值包括变量query的 let result array.filter(item > { return item.name.includes(query); }); 完整代码 wxml <input type"text" placeholder"请输入名称" placeholder-styl…

YOLO目标检测——番茄数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;番茄检测数据集说明&#xff1a;番茄目标检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标注框质量高&#xff0c;含voc(xml)、coco(json)和yolo(txt)三种格式标签…

YashanDB服务端个人版安装部署

介绍 崖山数据库系统YashanDB是深圳计算科学研究院完全自主研发设计的新型数据库系统&#xff0c;融入原创理论&#xff0c;支持单机/主备、共享集群、分布式等多种部署方式&#xff0c;覆盖OLTP/HTAP/OLAP交易和分析混合负载场景&#xff0c;为客户提供一站式的企业级融合数据…

2023年11月最新视频号下载提取工具?

视频号下载提取器教程&#xff1a; 1. 首先&#xff0c;在微信客户端中搜索并添加"下载小助手儿"并关注获取推送的消息。然后添加视频下载助手为好友&#xff0c;可以帮助你解析视频号链接。 2. 打开微信&#xff0c;并找到你想要提取链接的视频号。进入该视频页面后…

YOLO目标检测——红花数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;红花检测数据集可以用于监测和分析红花的生长情况&#xff0c;包括生长速度、叶面积、花朵数量等&#xff0c;为农民提供精确的决策支持&#xff0c;以提高红花产量和品质。数据集说明&#xff1a;红花检测数据集&#xff0c;真实场景的高质量图片数据…

我国陆地遥感卫星发展现状与展望

一、引言 从20世纪90年代末至今&#xff0c;我国陆地遥感卫星事业历经二十多年&#xff0c;实现了从无到有、从小到大、从弱到强的跨越发展。随着高分辨率对地观测系统重大专项&#xff08;高分专项&#xff09;、《陆海观测卫星业务发展规划&#xff08;2011—2020年&#xff…

CountDownLatch使用

常用于多线程场景&#xff0c;待多线程都结束后方可继续主线程逻辑处理 CodeConstant 常量类 import java.util.HashMap; import java.util.Map;public class CodeConstant {public static final Map<String, Map<String, String>> CODE new HashMap<>();…

零基础快速上手STM32开发(手把手保姆级教程)

零基础快速上手STM32开发&#xff08;手把手保姆级教程&#xff09; 1. 前言 作为一名嵌入式工程师&#xff0c;STM32 是必须要学习的一款单片机&#xff0c;同时这款单片机资料足够多&#xff0c;而且比较简单&#xff0c;非常适合初学者入门。 STM32 是一款由 STMicroelec…

酷柚易汛ERP - 商品库存余额表操作指南

1、应用场景 商品库存余额表用于查询商品在各仓库的实际结存量、单位成本以及成本等明细。 2、主要操作 打开【仓库】-【商品库存余额表】&#xff0c;可筛选仓库、商品、商品类别&#xff0c;导出/打印等操作见【销货单】不再赘述。 3、分享操作 库存余额分享&#xff0c;…

win7纯净版没有网卡驱动怎么办(msdn重装的系统)

当电脑重新安装Windows7系统之后&#xff0c;发现无法连接网络的情况&#xff0c;可以找一台能正常上网使用的电脑&#xff0c;打开浏览器软件&#xff0c;搜索“360驱动大师”&#xff0c;下载360驱动大师网卡版到U盘&#xff0c;然后拷贝到自己的win7电脑上安装网卡驱动&…

C++ final

参考:https://blog.csdn.net/qq_45358642/article/details/124232686#t2 不想让类继承 方式一&#xff1a;将类的构造函数设置为私有 子类不能调用父类构造函数初始化来实例化对象&#xff0c;所以不能继承 缺点&#xff1a;我们自己也不能够实例化出对象 class A { privat…

酷柚易汛ERP - 序列号跟踪表

1、应用场景 对于3C数码、医疗器械等行业&#xff0c;商品价值高且需要进行售后服务&#xff0c;需要对商品进行序列号管理&#xff0c;通过序列号跟踪表可查询每个序列号入库、出库、退货、调拨、盘点等流向。 2、主要操作 打开【仓库】-【序列号跟踪表】&#xff08;系统设…

2023.11.14-hive之表操作练习和文件导入练习

目录 需求1.数据库基本操作 需求2. 默认分隔符案例 需求1.数据库基本操作 -- 1.创建数据库test_sql,cs1,cs2,cs3 create database test_sql; create database cs1; create database cs2; create database cs3; -- 2.1删除数据库cs2 drop database cs2; -- 2.2在cs3库中创建…

洗地机哪个牌子最好用?洗地机品牌排行榜

近年来&#xff0c;洗地机相当热门&#xff0c;洗地机结合了扫地拖地吸地为一体的多功能清洁工具&#xff0c;让我们告别了传统方式打扫卫生&#xff0c;让我们清洁不再费劲&#xff0c;可是市面上的洗地机五花八门&#xff0c;怎么挑选到一个洗地机也是一个问题&#xff0c;下…