基于SpringBoot多数据源解决方案

最近在学习SpringBoot的时候,需要同时用两个不同的数据库连接服务,在网上学习了之后,下文以连接一个MySQL数据库和一个SqlServer数据库为例。

配置数据源连接信息

在配置文件中,配置对应的数据库连接信息,相比于单数据源时连接信息的url属性在多数据源时应该为jdbc-url,请注意下图红色部分:

image-20250127112939923

application.yml

spring:datasource:webproject:type: mysqldriver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://localhost:3306/webproject?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: password: workcontent:type: sqlServerdriver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriverjdbc-url: jdbc:sqlserver://localhost:1433;databaseName=myDatabase;encrypt=true;trustServerCertificate=true;characterEncoding=utf8;username: password: 

Maven配置数据库驱动

由于新版的官方Sqlserver驱动不支持TLSv1, TLSv1.1,我选择了较老的数据库驱动程序。

<!--    sqlserver驱动    -->
<dependency><groupId>com.microsoft.sqlserver</groupId><artifactId>mssql-jdbc</artifactId><version>7.4.1.jre11</version>
</dependency>
<!--	MYSQL驱动	-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency>

创建数据源配置类

以下文中的 WorkContentDataSourceConfig 为例,基本的流程如下:

配置类声明

配置要该数据源相关的Mapper所在的的包扫描和要注入的Sql工厂实例

image-20250127115339264

创建数据源DataSource

@ConfigurationProperties 用于注入application.yml中配置的数据库连接信息

@Primary 默认指定当前数据库,多数据源下需要配置@Primary,不然SpringBoot会找不到数据源注入,后续步骤最好也加上@Primary
在这里插入图片描述

创建Sql工厂,注册DataSource

@Qualifier 用于选择注入的bean对象

image-20250127121153606

创建事务管理器

image-20250127121313062

创建Sql模版对象

image-20250127121424311

具体配置类信息如下:

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;/*** @author yamu* @version 1.0* @description 工作库* @date 2025/1/23 10:49*/
@Configuration
@MapperScan(basePackages = {"org.cqw.baseproject.dao.workcontent"},sqlSessionFactoryRef = "workContentSqlSessionFactory")
public class WorkContentDataSourceConfig {@Bean(name = "workContentDataSource")@ConfigurationProperties(prefix = "spring.datasource.workcontent")@Primarypublic DataSource dataSource() {return DataSourceBuilder.create().build();}@Bean(name = "workContentSqlSessionFactory")@Primarypublic SqlSessionFactory sqlSessionFactory(@Qualifier("workContentDataSource") DataSource dataSource)throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/workcontent/*.xml"));return bean.getObject();}@Bean(name = "workContentTransactionManager")@Primarypublic DataSourceTransactionManager transactionManager(@Qualifier("workContentDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(name = "workContentSqlSessionTemplate")@Primarypublic SqlSessionTemplate sqlSessionTemplate(@Qualifier("workContentSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}
}
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;/*** @author yamu* @version 1.0* @description 项目库	* @date 2025/1/23 10:49*/
@Configuration
@MapperScan(basePackages = {"org.cqw.baseproject.dao.webproject"}, sqlSessionFactoryRef = "webProjectSqlSessionFactory")
public class WebProjectDataSourceConfig {@Bean(name = "webProjectDataSource")@ConfigurationProperties(prefix = "spring.datasource.webproject")public DataSource dataSource() {return DataSourceBuilder.create().build();}@Bean(name = "webProjectSqlSessionFactory")public SqlSessionFactory sqlSessionFactory(@Qualifier("webProjectDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/webproject/*.xml"));return bean.getObject();}@Bean(name = "webProjectTransactionManager")public DataSourceTransactionManager transactionManager(@Qualifier("webProjectDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(name = "webProjectSqlSessionTemplate")public SqlSessionTemplate sqlSessionTemplate(@Qualifier("webProjectSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}
}

创建实体

实体所在的包需要和创建配置类中的第一步的 配置类声明的@MapperScan的basePackages值相对应。

package org.cqw.baseproject.dao.webproject;
@Repository
public interface FunctionMenuDao {FunctionMenu queryById(int id);List<FunctionMenu> queryAll();
}

创建Mapper

由于有多个数据源,所以在/resources/mapper里面需要区分不同的数据库(即创建不同的文件夹,每个数据源扫描自己的mapper

.xml文件),如下图所示,注意和第三步创建Sql工厂,注册DataSource的SqlSessionFactorybean.setMapperLocations()里面的路径对应上,对于Mapper.xml里面的配置这里就不具体说明了。

image-20250127141023803

FunctionMenuMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.cqw.baseproject.dao.webproject.FunctionMenuDao"><select id="queryById" resultType="org.cqw.baseproject.entity.FunctionMenu">SELECT * FROM FunctionMenu WHERE id = #{id}</select><select id="queryAll" resultType="org.cqw.baseproject.entity.FunctionMenu">SELECT * FROM FunctionMenu WHERE isDel = '0' AND status = '1' ORDER BY depth, id</select>
</mapper>

测试

关于 Service 和 ServiceImpl 这里就省略了

FunctionMenuController

@RestController
@RequestMapping("/functionMenu")
public class FunctionMenuController {@Autowiredpublic FunctionMenuService functionMenuService;@GetMapping("getAllMenuList")public String getAllMenuList() {var data = functionMenuService.getAllMenuList();return R.success(data);//消息响应}
}

结果:

    public FunctionMenuService functionMenuService;@GetMapping("getAllMenuList")public String getAllMenuList() {var data = functionMenuService.getAllMenuList();return R.success(data);//消息响应}
}

结果:

image-20250127143701257

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

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

相关文章

二叉树的最大深度(C语言详解版)

一、摘要 嗨喽呀大家&#xff0c;leetcode每日一题又和大家见面啦&#xff0c;今天要讲的是104.二叉树的最大深度&#xff0c;思路互相学习&#xff0c;有什么不足的地方欢迎指正&#xff01;好啦让我们开始吧&#xff01;&#xff01;&#xff01; 二、题目简介 给定一个二…

穿心莲内酯(andrographolide)生物合成CYP72-文献精读106

Two CYP72 enzymes function as Ent-labdane hydroxylases in the biosynthesis of andrographolide in Andrographis paniculata 两种CYP72酶在穿心莲&#xff08;Andrographis paniculata&#xff09;中作为Ent-labdane羟化酶&#xff0c;在穿心莲内酯&#xff08;andrograp…

[SaaS] 内容创意生产平台

1.即梦 2.讯飞绘镜 typemovie 3.Krea.ai 4.Pika 5.runway 6.pixVerse 7.

DiffuEraser: 一种基于扩散模型的视频修复技术

视频修复算法结合了基于流的像素传播与基于Transformer的生成方法&#xff0c;利用光流信息和相邻帧的信息来恢复纹理和对象&#xff0c;同时通过视觉Transformer完成被遮挡区域的修复。然而&#xff0c;这些方法在处理大范围遮挡时常常会遇到模糊和时序不一致的问题&#xff0…

[c语言日寄]assert函数功能详解

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

【数据结构】_链表经典算法OJ:分割链表(力扣—中等)

目录 1. 题目描述及链接 2. 解题思路 2.1 思路1 2.2 思路2 2.3 思路3&#xff08;本题采取该解法&#xff09; 3. 题解程序 1. 题目描述及链接 题目链接&#xff1a;面试题 02.04. 分割链表 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你一个链表…

基于vue和elementui的简易课表

本文参考基于vue和elementui的课程表_vue实现类似课程表的周会议列表-CSDN博客&#xff0c;原程序在vue3.5.13版本下不能运行&#xff0c;修改两处&#xff1a; 1&#xff09;slot-cope改为v-slot 2&#xff09;return background-color:rgb(24 144 255 / 80%);color: #fff; …

【Unity3D】实现Decal贴花效果,模拟战旗游戏地形效果

目录 一、基础版 二、Post Process 辉光Bloom效果 矩形渐隐 涉及知识点&#xff1a;Decal贴花、屏幕后处理Bloom、屏幕空间构建世界空间、ChracterController物体移动、Terrain地形创建 一、基础版 Unity 2019.4.0f1 普通渲染管线&#xff08;非URP、非HDRP&#xff09; UR…

数据结构与算法学习笔记----求组合数

数据结构与算法学习笔记----求组合数 author: 明月清了个风 first publish time: 2025.1.27 ps⭐️一组求组合数的模版题&#xff0c;因为数据范围的不同要用不同的方法进行求解&#xff0c;涉及了很多之前的东西快速幂&#xff0c;逆元&#xff0c;质数&#xff0c;高精度等…

基于物联网设计的疫苗冷链物流监测系统

一、前言 1.1 项目开发背景 随着全球经济的发展和物流行业的不断创新&#xff0c;疫苗和生物制品的运输要求变得越来越高。尤其是疫苗的冷链物流&#xff0c;温度、湿度等环境因素的控制直接关系到疫苗的质量和效力&#xff0c;因此高效、可靠的冷链监控系统显得尤为重要。冷…

学习数据结构(1)时间复杂度

1.数据结构和算法 &#xff08;1&#xff09;数据结构是计算机存储、组织数据的方式&#xff0c;指相互之间存在⼀种或多种特定关系的数据元素的集合 &#xff08;2&#xff09;算法就是定义良好的计算过程&#xff0c;取一个或一组的值为输入&#xff0c;并产生出一个或一组…

基于RIP的MGRE实验

实验拓扑 实验要求 按照图示配置IP地址配置静态路由协议&#xff0c;搞通公网配置MGRE VPNNHRP的配置配置RIP路由协议来传递两端私网路由测试全网通 实验配置 1、配置IP地址 [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 15.0.0.1 24 [R1]int LoopBack 0 [R1-LoopBack0]i…

Oracle迁移DM数据库

Oracle迁移DM数据库 本文记录使用达梦官方数据迁移工具DTS&#xff0c;将Oracle数据库的数据迁移至达梦数据库。 1 数据准备 2 DTS工具操作步骤 2.1 创建工程 打开DTS迁移工具&#xff0c;点击新建工程&#xff0c;填写好工程信息&#xff0c;如图&#xff1a; 2.2 新建迁…

微服务(一)

文章目录 项目地址一、微服务1.1 分析User的Domian Verb和Nouns 二、运行docker和k8s2.1 Docker1. 编写dockerfile2. 创建docker image3. 运行docker使用指定端口4. 查看当前运行的镜像5. 停止当前所有运行的docker6. 删除不用的docker images7. 将本地的image上传到hub里 2.2 …

分享|instructionfine-tuning 指令微调是提高LLM性能和泛化能力的通用方法

《生成式AI导论》课程中&#xff0c;李宏毅老师提到一篇关于“ instruction fine-tuning” 指令微调的论文&#xff1a; 《Scaling Instruction-Finetuned Language Models》 摘要分享&#xff1a; 事实证明&#xff0c; 在一组以指令形式表达的数据集上微调语言模型可以提…

python生成图片和pdf,快速

1、下载安装 pip install imgkit pip install pdfkit2、wkhtmltopdf工具包&#xff0c;下载安装 下载地址&#xff1a;https://wkhtmltopdf.org/downloads.html 3、生成图片 import imgkit path_wkimg rD:\app\wkhtmltopdf\bin\wkhtmltoimage.exe # 工具路径&#xff0c;安…

Hive:基本查询语法

和oracle一致的部分 和oracle不一样的部分 排序 oracle中,在升序排序中&#xff0c;NULL 值被视为最大的值&#xff1b;在降序排序中&#xff0c;NULL 值被视为最小的值。 在MySQL中&#xff0c;NULL 被视为小于任何非空值。 在Hive中, NULL是最小的; Hive除了可以用order…

Python GUI 开发 | PySide6 辅助工具简介

关注这个框架的其他相关笔记&#xff1a;Python GUI 开发 | PySide6 & PyQt6 学习手册-CSDN博客 在上一章中&#xff0c;我们介绍了如何搭建 PySide6 & PyQt6 的开发环境。在搭建环境的时候我们配置了几个几个快捷工具&#xff0c;很多小伙伴可能都不知道是干啥用的。那…

hive:数据导入,数据导出,加载数据到Hive,复制表结构

hive不建议用insert,因为Hive是建立在Hadoop之上的数据仓库工具&#xff0c;主要用于批处理和大数据分析&#xff0c;而不是为OLTP&#xff08;在线事务处理&#xff09;操作设计的。INSERT操作会非常慢 数据导入 命令行界面:建一个文件 查询数据>>复制>>粘贴到新…

HarmonyOS:ForEach:循环渲染

一、前言 ForEach接口基于数组类型数据来进行循环渲染&#xff0c;需要与容器组件配合使用&#xff0c;且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。例如&#xff0c;ListItem组件要求ForEach的父容器组件必须为List组件。 API参数说明见&#xff1a;ForEa…