springboot + mybatis 多数据源切换

news2024/12/25 22:12:08

参考的b站博主写的
配置文件:

spring:
  datasource:
    db1:
      jdbc-url: jdbc:mysql://localhost:3306/interview_database?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 12345
      driver-class-name: com.mysql.cj.jdbc.Driver
    db2:
      jdbc-url: jdbc:mysql://localhost:3306/cailu-family-manager?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 12345
      driver-class-name: com.mysql.cj.jdbc.Driver

DataSourceChange.java 设定切换数据库的类,使用ThreadLocal


/**
 * @author HFQ
 * @version 1.0.0
 * @ClassName DataSourceChange.java
 * @Description 数据源切换
 * @createTime 2024年07月03日 22:56:00
 */
public class DataSourceChange {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal();
    // 设置默认数据库
    static {
        contextHolder.set("db1");
    }
    public static void setDB(String dbType){
        contextHolder.set(dbType);
    }
    public static String getDB(){
        return contextHolder.get();
    }
}

DynamicDataSource 类设置数据源,继承AbstractRoutingDataSource类基于查找键将getConnection()调用路由到各种目标DataSource之一的抽象DataSource实现。后者通常(但不一定)是通过一些线程绑定的事务上下文来确定的。

/**
 * @author HFQ
 * @version 1.0.0
 * @ClassName DynamicDataSource.java
 * @Description 设置数据源
 * @createTime 2024年07月03日 22:51:00
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceChange.getDB();
    }
}

DataSourceConfig类多数据源配置

/**
 * @author HFQ
 * @version 1.0.0
 * @ClassName DataSourceConfig.java
 * @Description 多数据源配置
 * @createTime 2024年07月03日 21:57:00
 */
@Configuration
public class DataSourceConfig {

    /**
     * @ConfigurationProperties用的反射来做这个功能
     * @return
     */
    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource db1(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource db2(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dynamicDataSource")
    @Primary
    public DataSource dynamicDataSource(@Qualifier("db1")DataSource db1,@Qualifier("db2")DataSource db2){
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 设置默认数据源 这个代码有点重复了,因为我们在DataSourceChange类中已经设定了默认数据库
        dynamicDataSource.setDefaultTargetDataSource(db1);
        HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("db1", db1);
        objectObjectHashMap.put("db2", db2);
        dynamicDataSource.setTargetDataSources(objectObjectHashMap);
        return dynamicDataSource;
    }

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

@ConfigurationProperties(prefix = “spring.datasource.db1”)
在Spring Boot中,@ConfigurationProperties注解用于将外部的配置属性(如application.yml或application.properties文件中的属性)映射到一个Java类的字段中。当你创建DataSourceBuilder并调用build方法时,Spring Boot会自动注入这些配置属性(使用的反射完成)。

测试一下
测试代码:

@Test
    public void testDb1(){
    // tagsMapper使用的是db1的连接,testMapper使用的是db2连接
        ArrayList<String> strings = new ArrayList<>();
        strings.add("女性");
        strings.add("广州");
        for (Integer tagsByName : tagsMapper.findTagsByNames(strings)) {
            System.out.println(tagsByName);
        }
        // 切换到db2
        DataSourceChange.setDB("db2");
        List<Map<String, Object>> maps = testMapper.selectTest();
        for (Map<String, Object> map : maps) {
            System.out.println(map.get("account_name").toString());
        }
    }

然后, 既然是多数据源,那mapper.xml文件也需要分层
所以我的mapper文件夹是这样的
在这里插入图片描述
mapper-locations 使用逗号分隔
yml配置文件:

mybatis:
  mapper-locations: classpath*:/mapper/db1/*.xml,classpath*:/mapper/db2/*.xml

执行结果:
在这里插入图片描述

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

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

相关文章

gda动态调试-cnblog

忽的发现gda有动态调试功能 动态监听返回值 框柱指定方法&#xff0c;选择调试方法&#xff0c;gda会自动监听函数的返回值&#xff0c;例如 自定义frida脚本 gda会自动生成hook该函数的frida脚本

RH850系列芯片深度剖析 1.8-内存管理之MPU

RH850系列芯片深度剖析 1.8-内存管理之MPU 文章目录 RH850系列芯片深度剖析 1.8-内存管理之MPU一、MPU简介1.1 功能特性1.2 系统保护标识符(SPID)二、保护区域设置2.1 保护区域属性设置2.2 保护区域设置注意事项2.2.1 跨越保护区域边界2.2.2 无效的保护区域设置2.2.3 保护违规…

LeetCode热题100刷题4:76. 最小覆盖子串、239. 滑动窗口最大值、53. 最大子数组和、56. 合并区间

76. 最小覆盖子串 滑动窗口解决字串问题。 labuladong的算法小抄中关于滑动窗口的算法总结&#xff1a; class Solution { public:string minWindow(string s, string t) {unordered_map<char,int> need,window;for(char c : t) {need[c];}int left 0, right 0;int …

LeetCode 算法:二叉树的最近公共祖先 III c++

原题链接&#x1f517;&#xff1a;二叉树的最近公共祖先 难度&#xff1a;中等⭐️⭐️ 题目 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点…

Streaming local LLM with FastAPI, Llama.cpp and Langchain

题意&#xff1a; 使用FastAPI、Llama.cpp和Langchain流式传输本地大型语言模型 问题背景&#xff1a; I have setup FastAPI with Llama.cpp and Langchain. Now I want to enable streaming in the FastAPI responses. Streaming works with Llama.cpp in my terminal, but…

Android车载开发中调试app与bat结合的丝滑小妙招

项目场景&#xff1a; 做Android车载的小伙伴调试app的时候常年就是手动adb命令三连&#xff0c;例如我常用的adb推送apk的命令 adb root adb remount adb push D:\workspace_atc\XSP3-10A\AutoSystemUIPlugin\app\release\CarSystemUI.apk /system/priv-app/CarSystemUI …

【Linux进程】进程优先级 Linux 2.6内核进程的调度

前言 进程是资源分配的基本单位, 在OS中存在这很多的进程, 那么就必然存在着资源竞争的问题, 操作系统是如何进行资源分配的? 对于多个进程同时运行, 操作系统又是如何调度达到并发呢? 本文将以Linux kernel 2.6为例 , 向大家介绍进程在操作系统中 (OS) 的调度原理; 1. 进程优…

什么是网络抓取|常见用例和问题

你可能听说过数据被称为现代信息社会的新石油。由于线上信息量庞大&#xff0c;能够有效地收集和分析网页数据已经成为企业、研究人员和开发人员的关键技能。这就是网页抓取技术的用武之地。网页抓取&#xff0c;也称为网页数据提取&#xff0c;是一种强大的技术&#xff0c;能…

国际上备考所有AWS云计算/IT证书的五大优质免费课程网站

最近越来越多的小伙伴来问小李哥&#xff0c;小李哥亚马逊云科技AWS认证大满贯是在哪里上课复习的呢&#xff1f;全部上付费课程那不是一笔巨款吗&#xff1f;小李哥这次来盘点备考国际上IT证书的5大优质免费课程网站(不只是亚马逊云科技AWS的课程&#xff0c;其他课程同样可以…

46.修复HOOK对代码造成的破坏

上一个内容&#xff1a;45.使用hook点链表实现指定跳转 以 45.使用hook点链表实现指定跳转 它的代码为基础进行修改 此代码已实现无敌与秒杀功能 HOOKPOINT.h文件里的修改 #pragma oncetypedef struct CPUINFO {unsigned eflags;unsigned edi;unsigned esi;unsigned ebp;un…

【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(十)-git(2)

下面是一些git的常用命令和基本操作&#xff0c;可以当做平常的笔记查询&#xff0c;用于学习&#xff01;&#xff01;&#xff01; 文章目录 前言 一、git 二、git常用命令 总结 前言 下面是一些git的常用命令和基本操作&#xff0c;可以当做平常的笔记查询&#xff0c;用于…

【python】Python中常用的数据结构——列表、元组和字典

python中的数据结构 列表、元组、字典的区别元组&#xff0c;字典&#xff0c;列表三者之间如何实现嵌套生成一个单一元素的元组、列表列表的地址列表、元组和字典的增删改查 列表、元组、字典的区别 列表、元组和字典是Python中常用的数据结构&#xff0c;它们各自有不同的特…

Infinitar链游新发展新机遇

区块链游戏市场在近年来经历了显著增长&#xff0c;吸引了大量的投资和关注。随着加密货币和NFT&#xff08;非同质化代币&#xff09;概念的普及&#xff0c;越来越多的投资者、游戏开发者和看到了区块链技术在游戏领域的应用潜力&#xff0c;纷纷涌入市场。区块链游戏的用户量…

昇思25天学习打卡营第07天 | 函数式自动微分

昇思25天学习打卡营第07天 | 函数式自动微分 文章目录 昇思25天学习打卡营第07天 | 函数式自动微分函数与计算图微分函数与梯度Stop GradientAuxiliary data 神经网络梯度计算总结打卡 神经网络的训练主要使用反向传播算法&#xff0c;首先计算模型预测值&#xff08;logits&am…

Prompt-Free Diffusion: Taking “Text” out of Text-to-Image Diffusion Models

CVPR2024 SHI Labshttps://arxiv.org/pdf/2305.16223https://github.com/SHI-Labs/Prompt-Free-Diffusion 问题引入 在SD模型的基础之上&#xff0c;去掉text prompt&#xff0c;使用reference image作为生成图片语义的指导&#xff0c;optional structure image作为生成图片…

【Leetcode笔记】406.根据身高重建队列

文章目录 1. 题目要求2.解题思路 注意3.ACM模式代码 1. 题目要求 2.解题思路 首先&#xff0c;按照每个人的身高属性&#xff08;即people[i][0]&#xff09;来排队&#xff0c;顺序是从大到小降序排列&#xff0c;如果遇到同身高的&#xff0c;按照另一个属性&#xff08;即p…

关于SAP SAP NetWeaver AS JAVA 授权问题漏洞(CVE-2020-6287)及修复

路径参考 SAP NetWeaver AS Java 严重漏洞 (CVE-2020-6287) 安全通告 - 威胁通告 - 绿盟科技-巨人背后的专家 SAP NOTE ​​​​​​https://me.sap.com/notes/2939665 找到路径 导航到 http(s)://<主机名>:port/nwa -> 配置 -> 基础架构 -> Java HTTP 提供…

Leetcode - 周赛403

目录 一&#xff0c;3200. 三角形的最大高度 二&#xff0c;3195. 包含所有 1 的最小矩形面积 I 三&#xff0c;3196. 最大化子数组的总成本 四&#xff0c;3197. 包含所有 1 的最小矩形面积 II 一&#xff0c;3200. 三角形的最大高度 本题是一道模拟题&#xff0c;可以先排…

从零开始手写STL库:Vector

从零开始手写STL库–Vector部分 文章目录 从零开始手写STL库--Vector部分Vector是什么Vector需要包含什么函数1&#xff09;基础成员函数2&#xff09;核心功能 基础成员函数的编写核心功能函数的编写总结 Vector是什么 std::vector 是一个动态数组&#xff0c;它在内存中以连…

安装Nginx以及简单使用 —— windows系统

一、背景 Nginx是一个很强大的高性能Web和反向代理服务&#xff0c;也是一种轻量级的Web服务器&#xff0c;可以作为独立的服务器部署网站&#xff0c;应用非常广泛&#xff0c;特别是现在前后端分离的情况下。而在开发过程中&#xff0c;我们常常需要在window系统下使用Nginx作…