掌握 Spring Boot + MyBatis-Plus 动态数据源切换,只要5分钟!

数据量猛增,通过动态数据源切换,我们不仅能提高查询效率,还能保证系统的高可用性。

通过将操作集中在主库操作分散到多个从库,可以有效减轻数据库的压力。

pom.xml中添加以下依赖:

 

xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

application.yml中的数据源配置

 

yaml

spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/primary_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
replica:
url: jdbc:mysql://localhost:3306/replica_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver

在这里,我们配置了两个数据源,

一个主库primary

一个从库replica

这样我们就可以在业务中区分读写操作了。

枚举类型与数据源上下文

为了实现动态数据源切换,我们需要定义数据源的类型,并通过上下文管理当前数据源。

DatabaseType枚举的设计
 

java

public enum DatabaseType {
PRIMARY, // 主库
REPLICA // 从库
}

DataSourceContextHolder的实现与作用
 

java

public class DataSourceContextHolder {

// 使用ThreadLocal存储当前线程的数据源类型
private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();

// 设置数据源类型
public static void setDatabaseType(DatabaseType type) {
contextHolder.set(type);
}

// 获取数据源类型
public static DatabaseType getDatabaseType() {
return contextHolder.get();
}

// 清除数据源类型
public static void clearDatabaseType() {
contextHolder.remove();
}
}

通过上述代码,我们可以在不同的线程中安全地设置和获取当前数据源的类型。

动态数据源的实现机制

动态数据源的核心是继承并重写AbstractRoutingDataSource类。

DynamicDataSource类的继承与重写
 

java

public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// 从上下文中获取当前数据源的类型
return DataSourceContextHolder.getDatabaseType();
}
}

通过继承AbstractRoutingDataSource,我们可以在运行时根据上下文动态切换数据源

为了方便使用,我们可以设计一个自定义注解@DataSource来标识需要切换数据源的方法或类。

@DataSource注解的定义
 

java

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
DatabaseType value() default DatabaseType.PRIMARY; // 默认使用主库
}

注解在类和方法上的使用示例

图片

使用自定义注解,我们可以方便地在方法上切换数据源。

数据源切换的AOP实现

通过AOP,我们可以在方法执行前后切换数据源。

DataSourceAspect切面类的编写
 

java

@Aspect
@Component
public class DataSourceAspect {

@Around("@annotation(dataSource)")
public Object switchDataSource(ProceedingJoinPoint point, DataSource dataSource) throws Throwable {
try {
// 在方法执行前设置数据源
DataSourceContextHolder.setDatabaseType(dataSource.value());
return point.proceed(); // 执行目标方法
} finally {
// 在方法执行后清除数据源
DataSourceContextHolder.clearDatabaseType();
}
}
}

通过环绕通知,我们可以在方法执行前后设置和清除数据源,确保数据源切换的正确性。

配置类负责创建和管理多个数据源,并将它们注册到Spring容器中。

DataSourceConfig的职责与实现
 

java

@Configuration
public class DataSourceConfig {

@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build(); // 创建主数据源
}

@Bean
@ConfigurationProperties(prefix = "spring.datasource.replica")
public DataSource replicaDataSource() {
return DataSourceBuilder.create().build(); // 创建从数据源
}

@Bean
public DataSource dataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DatabaseType.PRIMARY, primaryDataSource());
targetDataSources.put(DatabaseType.REPLICA, replicaDataSource());

DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setDefaultTargetDataSource(primaryDataSource()); // 设置默认数据源
dataSource.setTargetDataSources(targetDataSources); // 设置目标数据源
return dataSource;
}
}

通过这个配置类,我们可以将多个数据源注册到Spring容器中,并设置默认数据源和目标数据源。

为了在MyBatis-Plus中使用动态数据源,我们需要配置SqlSessionFactory和SqlSessionTemplate。

DynamicDataSourceConfig的配置
 

java

@Configuration
@MapperScan("com.example.mapper")
public class DynamicDataSourceConfig {

@Autowired
private DataSource dataSource;

@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}

@Bean
public SqlSessionTemplate sqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
}

通过配置SqlSessionFactorySqlSessionTemplate,我们可以确保MyBatis-Plus能够使用动态数据源。

主从数据库同步策略

实时同步方案的推荐

图片

图片

最后说一句(求关注!别白嫖!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

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

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

相关文章

Qt系统机制

Qt系统 Qt文件概述输入输出设备类QFileQFileInfoQt多线程Qt多线程常用API使用Qt多线程 线程安全互斥锁读写锁条件变量信号量 Qt网络QUdpSocketQNetworkDatagram设计一个UDP回显服务器QTcpServerQTcpSocketTcp版本的回显服务器HttpClient核心API Qt 音频Qt视频 Qt文件概述 ⽂件操…

入门Pandas必练习100题基础到进阶|阶级教程2

作者:郭震 51. How to get the row number of the nth largest value in a column? Find the row position of the 5th largest value of column a in df. # input df pd.DataFrame(np.random.randint(1, 30, 30).reshape(10,-1), columnslist(abc)) df# Solution 1# argsort…

HEML+CSS超详细基础知识

一些快捷键 ctrl/ 是注释 ctrld 是选中多个相同字 ctrls保存 altZ自动换行 altshift选中多行 HTML认知 基础认知 html初尝试 HTML页面结构介绍 初次尝试 开始动手写一个网页 先新建一个文件&#xff0c;记得后缀要命名成html 然后shift&#xff01;&#xff0c;就会自动…

《系统架构设计师教程(第2版)》第13章-层次式架构设计理论与实践-01-层次式体系结构概述

文章目录 1. 常用层次是架构2. 层次式架构设计的注意点2.1 污水池反模式2.2 应用变得庞大 本章教材又赘述了一遍架构的定义和层次架构风格的概述&#xff0c;我之前的笔记都写了 架构的定义回看《第7章-系统架构设计基础知识-01-软件架构&#xff08;Software Architecture&…

学习测试15-实战6-根据说明书建工程

CAN协议说明书&#xff1a;含义 一&#xff0c;得到表 1&#xff0c;先建信号 2&#xff0c;建报文&#xff0c;将对应信号拖入其中 3&#xff0c;建节点&#xff0c;将报文添加进TX msg里 调整起始位 数据库建立完成 二&#xff0c;不需要面板&#xff0c;直接导入数据库&…

HTTPS证书价格一年多少钱?如何购买?

目前市面上所有免费一年期HTTPS已经全部下架&#xff0c;付费证书已经成为主流。HTTPS证书的价格受多种因素影响&#xff0c;具体有以下几种&#xff1a; 一、证书类型 单域名证书价格一般在几百元左右&#xff0c;通配符价格高一些&#xff0c;千元以上&#xff0c;多域名价…

《知识点扫盲 · Redis 序列化器》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

米家护眼台灯怎么样?书客、米家、明基三款护眼台灯大PK

市面上出现的护眼台灯款式不得不说真的很多&#xff0c;大家若是想要在护眼台灯这个大市场里选购到一款性价比高、质量过关、口碑好且还真的实用的护眼台灯需要认真做好攻略。所以&#xff0c;我们要有技巧的对这些台灯进行筛选&#xff0c;避开那些三无的、网红品牌、无知名度…

http协议与nginx

动态页面与静态页面的差别&#xff1a; &#xff08;1&#xff09;URL不同 静态⻚⾯链接⾥没有“?” 动态⻚⾯链接⾥包含“&#xff1f;” &#xff08;2&#xff09;后缀不同 (开发语⾔不同) 静态⻚⾯⼀般以 .html .htm .xml 为后缀 动态⻚⾯⼀般以 .php .jsp .py等为后…

【吊打面试官系列-Dubbo面试题】Dubbo SPI 和 Java SPI 区别?

大家好&#xff0c;我是锋哥。今天分享关于 【Dubbo SPI 和 Java SPI 区别&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; Dubbo SPI 和 Java SPI 区别&#xff1f; JDK SPI JDK 标准的 SPI 会一次性加载所有的扩展实现&#xff0c;如果有的扩展吃实话很耗时&…

Python中的类型注解和静态类型检查使用详解

概要 Python作为一种动态类型语言,其灵活性和易用性使其广受欢迎。然而,动态类型也带来了一些问题,如代码可读性差和运行时错误等。为了提高代码质量和可维护性,Python从3.5版本开始引入了类型注解(Type Hints),并且借助第三方工具可以实现静态类型检查。本文将详细介绍…

Python学生信息管理系统

一、需求分析 学生管理系统应具备的功能 1、添加学生及成绩信息 2、将学生信息保存到文件中 3、修改和删除学生信息 4、查询学生信息 5、根据学生成绩进行排序 6、统计学生的总分 二、系统设计 2.1、学生信息管理系统的系统功能结构&#xff08;7大模块&#xff09; 1、录入…

vue里给img的src绑定数据失效

起因 在v-for遍历数据时想要通过给img的src单向绑定 图片路径时出现问题 解决过程 上网查说是webpack构建时识别不到&#xff0c;直接不单绑数据&#xff0c;写死试试看 解决方案 直接require导入图像文件模块

AI Agent调研--7种Agent框架对比!盘点国内一站式Agent搭建平台,一文说清差别!大家都在用Agent做什么?

代理&#xff08;Agent&#xff09;乃一种智能实体&#xff0c;具备自主环境感知与决策行动能力&#xff0c;旨在达成既定目标。作为个人或组织之数字化替身&#xff0c;AI代理执行特定任务与交易&#xff0c;其核心价值在于简化工作流程&#xff0c;削减繁复性&#xff0c;并有…

MSPM0G3507之电赛小车

一、前言 本文没什么技术分享&#xff0c;纯聊天。以下内容均为笔者的浅薄理解&#xff0c;有不对的地方还请多多包涵。 二、相关配置 主控单元&#xff1a;MSPM0G3507SPTR&#xff08;48角&#xff09; 编译环境&#xff1a;Keil5.33、5.39&#xff08;推荐&#xff09;都可 …

Redisson关键参数含义介绍

一、threads&#xff08;线程池数量&#xff09; 对应executor&#xff08;线程池&#xff09; 默认值: 当前处理核数量 * 2 这个线程池数量被所有RTopic对象监听器&#xff0c;RRemoteService调用者和RExecutorService任务共同共享。 二、nettyThreads &#xff08;Netty线…

数据结构与算法-关于堆的基本排序介绍

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、堆排序…

Springboot使用Redis实现分布式锁

1、使用场景和实现方案&#xff1a; 使用场景&#xff1a;本地锁如Lock和Syncronized只能锁住本地进程&#xff0c;在分布式应用中&#xff0c;需要使用分布式锁来更好实现特定的业务。 实现方案&#xff1a;有多种&#xff0c;比如使用mysql、zookeeper、redis&#xff0c;各…

80端口被system占用 ,system进程是4!!!亲测-----解决

最近需要使用nginx&#xff0c;发现80端口北占用 正常情况下&#xff0c;查看那个进程占用&#xff0c;然后找到对应的程序&#xff0c;关闭对应的就可了。 使用 netstat 命令&#xff1a; 打开命令提示符&#xff08;以管理员身份&#xff09;。输入命令 netstat -ano | fi…

vue3 + element plus使用iconfont 自定义font组件颜色大小可修改

vue3 element plus使用iconfont 自定义font组件&颜色大小可修改这里写自定义目录标题 自定义SvgIcon.vue引入iconfontApp.vue中引入组件更改图标大小 参考网上方案新建SvgIcon.vue&#xff0c;但没说明怎么修改颜色及大小&#xff0c;我在这个博客中简单提供下。 自定义Sv…