Springboot整合多数据源,Mybatis-plus,druid 的实现

第一步、导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.tiger</groupId><artifactId>DoubleDataSource</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!--    声明springboot的版本号 --><spring-boot.version>2.5.5</spring-boot.version></properties><!--  引入springboot官方提供的所有依赖的版本号定义,如果项目中使用相关依赖,可以不必写版本号了--><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!--    引入springboot的web项目的依赖        --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 基于 mybatis plus 的dao层的相关依赖 start--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><!-- 德鲁伊启动器     --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version></dependency><!--    数据库依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- 基于 mybatis plus 的dao层的相关依赖 end--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.3.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--  springboot测试依赖   --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

第二步、yml文件

spring:autoconfigure:exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfiguredatasource:dynamic:primary: master #设置默认的数据源或者数据源组,默认值即为masterdatasource:master:username: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.52.130:3306/firstDB?useSSL=false&useUnicode=true&characterEncoding=utf8type: com.alibaba.druid.pool.DruidDataSourceslave_1:username: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://192.168.52.130:3306/secondDB?useSSL=false&useUnicode=true&characterEncoding=utf8type: com.alibaba.druid.pool.DruidDataSource#......省略#以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2

第三步、mapper service serviceImpl

package com.tiger.DoubleDataSourceApp.mapper;import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiger.DoubleDataSourceApp.pojo.Student;public interface FirstStudentMapper extends BaseMapper<Student> {
}
package com.tiger.DoubleDataSourceApp.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.tiger.DoubleDataSourceApp.pojo.Student;public interface FirstStudentService extends IService<Student> {
}
package com.tiger.DoubleDataSourceApp.service.impl;import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiger.DoubleDataSourceApp.mapper.FirstStudentMapper;
import com.tiger.DoubleDataSourceApp.pojo.Student;
import com.tiger.DoubleDataSourceApp.service.FirstStudentService;
import org.springframework.stereotype.Service;@Service
@DS("master")
public class FirstStudentServiceImpl extends ServiceImpl<FirstStudentMapper, Student> implements FirstStudentService {
}
package com.tiger.DoubleDataSourceApp;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan(basePackages = "com.tiger.DoubleDataSourceApp.mapper")
public class DDSApplication {public static void main(String[] args) {SpringApplication.run(DDSApplication.class,args);}
}
如何在同一个方法中切换数据源?
DynamicDataSourceContextHolder.push("slave");//slave即数据源名称
//中间执行你的业务sql
DynamicDataSourceContextHolder.clear();

第四步、整合事务测试

package com.tiger.DoubleDataSourceApp.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.tiger.DoubleDataSourceApp.pojo.Student;import java.util.List;public interface SecondStudentService extends IService<Student> {boolean saveList(List<Student> list);
}
package com.tiger.DoubleDataSourceApp.service.impl;import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiger.DoubleDataSourceApp.mapper.FirstStudentMapper;
import com.tiger.DoubleDataSourceApp.pojo.Student;
import com.tiger.DoubleDataSourceApp.service.FirstStudentService;
import com.tiger.DoubleDataSourceApp.service.SecondStudentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
@DS("slave_1")
@Transactional(rollbackFor = Exception.class)
public class SecondStudentServiceImpl extends ServiceImpl<FirstStudentMapper, Student> implements SecondStudentService {@Overridepublic boolean saveList(List<Student> list) {boolean b = this.saveBatch(list);int i=1/0;return b;}
}
package com.tiger.DoubleDataSourceApp.service.impl;import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiger.DoubleDataSourceApp.mapper.FirstStudentMapper;
import com.tiger.DoubleDataSourceApp.pojo.Student;
import com.tiger.DoubleDataSourceApp.service.FirstStudentService;
import com.tiger.DoubleDataSourceApp.service.SecondStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
@DS("master")
public class FirstStudentServiceImpl extends ServiceImpl<FirstStudentMapper, Student> implements FirstStudentService {@Autowiredprivate SecondStudentService secondStudentService;@Overridepublic int syncDataBase() {List<Student> list = this.list();secondStudentService.saveList(list);return 0;}
}
package com.tiger.DoubleDataSourceApp.mapper;import com.tiger.DoubleDataSourceApp.pojo.Student;
import com.tiger.DoubleDataSourceApp.service.FirstStudentService;
import lombok.AllArgsConstructor;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class SencondStudentMapperTest {@Autowiredprivate FirstStudentMapper firstStudentMapper;@Autowiredprivate FirstStudentService firstStudentService;@Testvoid name() {firstStudentService.syncDataBase();}@Testvoid test1() {firstStudentMapper.insert(new Student(null,"张三",3));}
}

经过测试能够回滚.

mapper上也能加,加了代理的对象,就是对应的数据源,但是最好是在serviceImpl方法上加,可以做事务处理

需要注意的是,不能再两个不同数据源里加事务,事务只能对应一个数据源.

   @Override@Transactional(rollbackFor = Exception.class)public int syncDataBase() {List<Student> list = this.list();System.out.println(list);DynamicDataSourceContextHolder.push("slave_1");List<Student> list1 = this.list();System.out.println(list1);DynamicDataSourceContextHolder.poll();DynamicDataSourceContextHolder.push("slave_1");List<Student> list2 = this.list();System.out.println(list2);DynamicDataSourceContextHolder.poll();DynamicDataSourceContextHolder.push("master");List<Student> list3 = this.list();System.out.println(list3);DynamicDataSourceContextHolder.clear();List<Student> list4 = this.list();System.out.println(list4);return 0;}

这样的结果,就是让这里面所有的都变成一个数据源

DynamicDataSourceContextHolder.poll();
DynamicDataSourceContextHolder.clear();

的区别

前者只是弹出当前数据源,然后使用标记的DS数据源

clear强制清楚本地数据源,直接用 master 数据源

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

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

相关文章

IPv4 VS IPv6代理全解,跨境电商代理IP选哪种?

IP&#xff08;互联网协议&#xff09;被网站用来收集用户位置信息。当今最流行的两种互联网协议是 IPv4 和 IPv6。 在我们选择IP代理的过程中可以看到IPv4、IPv6两种类型&#xff0c;他们有何区别&#xff1f;如何选择&#xff1f;下面为大家讲解&#xff01; 在这篇文章中&a…

数据库开发之子查询的详细解析

1.4 子查询 1.4.1 介绍 SQL语句中嵌套select语句&#xff0c;称为嵌套查询&#xff0c;又称子查询。 SELECT * FROM t1 WHERE column1 ( SELECT column1 FROM t2 ... ); 子查询外部的语句可以是insert / update / delete / select 的任何一个&#xff0c;最常见…

【JavaScript】Set、Map、WeakSet、WeakMap

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

数据治理认证大揭秘:CDMP、CDGA与CDGP,你了解多少?

IT码农们&#xff0c;你们是否经常被问到关于数据治理认证CDMP、CDGA和CDGP的问题&#xff1f;今天就来给大家好好科普一下&#xff01; &#x1f52e; CDMP&#xff1a;数据治理的基石 CDMP&#xff0c;即数据管理专业人士认证&#xff0c;是迈向数据治理旅程的起点。它为你打…

uniapp 统一获取授权提示和48小时间隔授权

应用商店审核要求 获取权限前需要给提示&#xff0c;拒绝之后48小时不能给弹窗授权 项目用的是uniapp getImagePermission(v?: string, tag?: any, source?: any, proj?: any) {// proj proj || vueSelf.$proj(tag, source);let data {state: false,//是否原生授权denied…

每日一练 | 华为认证真题练习Day155

1、两台路由器通过多条物理链路建立一个逻辑BGP对等体时&#xff0c;必须使用peer connect-interface命令。 A. 正确 B. 错误 2、对于链路状态路由协议&#xff0c;在入方向过滤路由实际上可以阻断链路状态信息的传递&#xff0c;过滤的效果是路由不能被加到本地路由表中&…

分享七种msvcp140.dll丢失的解决方法,帮助大家解决msvcp140.dll丢失

msvcp140.dll是一个重要的系统文件&#xff0c;它是微软视觉C可再发行包的一部分。这个动态链接库&#xff08;DLL&#xff09;文件对于运行那些用Visual Studio 2015及其更新版本开发的应用程序至关重要。在Windows操作系统中&#xff0c;DLL文件提供执行许多常见任务的必要指…

【回溯】装载问题Python实现

文章目录 [toc]问题描述问题转换回溯法时间复杂性Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;回溯法 问题描述 有一批共 n n n个集装箱要装上 2 2 2艘载重量分别为 c 1 c_{1} c1​和 c 2 c_{2} c2​的轮船&#xff0c;其中集装箱 i i i的重量为 w i w_{i} w…

async和await的使用

async和await是promise的一种语法糖,也就是更简单易懂的写法。 在很多项目中,你会经常看到async和await的配合使用,看到原始的promise写法反而不多,就是因为async-await这种写法是用同步的语法去实现异步的逻辑。 基础使用 原生promise写法 let value nulllet proFn new P…

AR智慧校园三维主电子沙盘系统研究及应用

一 、概述 易图讯科技(www.3dgis.top)自主研发的智慧校园三维主电子沙盘系统&#xff0c;采用B/S架构模式&#xff0c;采用自主可控高性能WebGIS可视化引擎&#xff0c;支持多用户客户端通过网络请求访问服务器地图和专题数据&#xff0c;提供地理信息数据、专题数据的并发访问…

Temu和Shein争端再起:海外电商“围城”下,一场厮杀正在酝酿

两家中国电商出海“双子星”&#xff0c;争端再起。 最近&#xff0c;美国法院最新公开临时限制令显示&#xff0c;跨境电商平台Temu&#xff08;特木&#xff09;的男装、休闲装、运动服等50款产品涉侵权时尚电商平台Shein&#xff08;希音&#xff09;&#xff0c;并向Temu旗…

智能优化算法应用:基于蜣螂算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蜣螂算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蜣螂算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蜣螂算法4.实验参数设定5.算法结果6.参考文献7.MA…

十二.视图

视图 1.常见数据库对象2.视图概述2.1为什么使用视图2.2视图的理解 3.创建视图3.1创建单表视图3.2创建多表联合试图3.3基于试图创建视图 4.查看视图5.更新视图的数据5.1一般情况5.2不可更新的视图 6.修改、删除视图6.1修改视图6.2删除视图 7.总结7.1视图优点7.2视图不足 1.常见数…

【C语言:编译、预处理详解】

文章目录 1.编译2.预处理2.1宏定义2.1.1预定义符号2.1.2#define定义常量2.1.3#define定义宏2.1.4do-while-zero2.1.5宏的注意事项2.1.6宏与函数的对比 2.2条件编译2.3文件包含 3.offsetoff4.#与##4.1. #号4.2 ##号 1.编译 我们都知道&#xff0c;一个程序如果想运行起来要经过…

Python如何实现邮件的发送

python笔记- 发送邮件 依赖&#xff1a; Python代码实现发送邮件&#xff0c;使用的模块是smtplib、MIMEText&#xff0c;实现代码之前需要导入包&#xff1a; import smtplib from email.mime.text import MIMEText 使用163邮件发送邮件&#xff0c;具体代码实现如下&#x…

基于SpringBoot的自习室预约管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的自习室预约管理系统,ja…

Tofu5m目标识别跟踪模块 跟踪模块

Tofu5m 是高性价比目标识别跟踪模块&#xff0c;支持可见光视频或红外网络视频的输入&#xff0c;支持视频下的多类型物体检测、识别、跟踪等功能。 产品支持视频编码、设备管理、目标检测、深度学习识别、跟踪等功能&#xff0c;提供多机版与触控版管理软件&#xff0c;为二次…

基于SpringBoot的考编论坛网站

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SpringBoot的考编论坛网站,java项目…

vivado 错误路径

错误路径 假路径是指拓扑上存在于设计中的路径&#xff0c;但有以下两种情况之一&#xff1a;&#xff08;1&#xff09;不起作用&#xff1b;或&#xff08;2&#xff09;不需要定时。因此&#xff0c;在定时期间应忽略错误路径分析。 错误路径的示例包括&#xff1a; •添…

渗透测试——1.4主动扫描

主动扫描是别人可以发觉的情报收集 一、nmap的使用 1.nmap<目标主机>:最常用的扫描方式 有nmap版本、扫描时间 “host is up”表示目标主机处于开机状态、“not shown”未开放端口 有四个端口是开的&#xff08;135.139.445.912&#xff09; 2.nmap -p<端口范围…