sqlhelper集成dynamic多数据源的分页问题(非教学向)

2023-11-06

一.问题描述

最近接手(顶锅)了公司的框架维护工作,第一项任务就是集成dynamic多数据源框架。(dynamic官方使用文档,本文不是教学,有兴趣的小伙伴可以自己查阅文档)。集成dynamic之后,一切都很顺利,但是测试到SQLHelper框架的分页功能,出错了:SQLHelper分页功能,全部是按照dynamic指定的primary数据源来处理分页sql的。比如我配置了mysql和oracle两个数据源,并且指定mysql为primary主数据源,然后不管使用哪个数据源进行查询,SQLHelper都是按照primary指定的主数据源mysql进行分页处理,导致用oracle数据源时分页语句sql报错。

二.解决思路

1.找到分页sql的处理入口

通过断点调试,找到了SQLHelper的com.jn.sqlhelper.dialect.internal.Dialect类和处理语句有关(实际上Dialect是一个接口,抽象子类AbstractDialect的属性LimitHandler才是实际sql的逻辑处理类,processSql是处理方法入口。为了方便理解,就以Dialect概括,一个Dialect对应一种数据源的处理)
在这里插入图片描述

2.Dialect和databaseId有关

databaseId其实就是数据源类型,Dialect是处理sql的类,每一种数据源对应一个Dialect,通过databaseId获取对应的Dialect然后进行sql加工处理,com.jn.sqlhelper.mybatis.plugins.pagination的PaginationHandler类beginIfSupportsLimit方法:
在这里插入图片描述

3.实际出问题的地方

其实就是databaseId的获取,com.jn.sqlhelper.mybatis包下MybatisUtils类getDatabaseId方法:

在这里插入图片描述

红框才是罪魁祸首(暂且先不看蓝框),通过断点调试,发现获取的是org.apache.ibatis.session.Configuration类的databaseId。那问题来了,Configuration类的databaseId是什么时候设置的呢?通过Configuration的setDatabaseId方法的断点调试,发现该方法是项目启动的时候才调用。org.mybatis.spring.SqlSessionFactoryBean类的buildSqlSessionFactory方法
在这里插入图片描述

这也解释通了为什么SQLHelper只按照某种数据源来处理分页语句

4.为什么按照primary指定的主数据源处理?

一切从简,上关键代码(接Configuration的setDatabaseId方法):
com.baomidou.dynamic.datasource.DynamicRoutingDataSource类的determineDataSource方法
在这里插入图片描述
com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder类的peek()方法返回当前线程/代码使用的数据源名称,启动时没有触发push操作,所以返回为空。
在这里插入图片描述
空值则返回primary指定的默认数据库,所以Configuration的databaseId是dynamic在配置文件用primary指定的主数据源:
在这里插入图片描述
5.DynamicDataSourceContextHolder的push:
dynamic会将当前线程使用的数据源存入threadlocal里
com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationInterceptor.invoke方法,会将当前线程使用的数据源名称存入
在这里插入图片描述
这个push触发的机制,应该是dynamic注解扫描到的地方。这也解释了为什么启动的时候peek返回空,因为没有触发push操作。

三.解决方案:

既然知道问题所在,那么就有解决思路了:MybatisUtils的getDatabaseId方法,返回正确的数据就行。

1.不走全局获取databaseId

如果能提前知道现在的数据源是什么,然后通过这个数据源获取databaseId就好了。巧的是DynamicDataSourceContextHolder类的peek()是一个静态方法,并且入参MappedStatement ms可以获取到dynamic配置的所有数据源信息:
在这里插入图片描述

2.通过connection获取databaseId

其实就是二.3的蓝框放前面就行,由于集成了连接池,所以不需要担心查询之前多连接一次数据库。tx.getConnection()源码有兴趣的也可以翻一下哦。

3.后续版本优化

四.小结

  1. SQLHelper根据databaseId(数据源类型)处理分页语句的类是LimitHandler;databaseId和LimitHandler、Dialect,是1:1:1的关系。
  2. springboot+tx.mybatis+dynamic+SQLHelper的技术选型下,SQLHelper在dynamic情况下分页处理有问题。
  3. 处理方案经实践,mybatis是完全可以适配的。不知道其他orm框架是否适用!

五.彩蛋时间

最近终于稍微脱离了CRDU的业务代码,开始往底层摸索了。框架需要适配dynamic,其实我也是什么都不懂,没办法只能查资料看看dynamic是什么,然后通过断点调试的方式探索开源框架的处理流程,说实话,最后发现问题并且解决问题的时候,还是有一点自豪感和成就感的!
框架这个版本的需求功能,需要用到的技术栈其实我基本没听过,但是有压力就有动力,能让自己多学一些总是好的!
另外附上和SQLHelper作者在github上的讨论地址:此次论剑,略输一筹(滑稽,HSPCode就是本萌新)

萌新发言,不喜勿喷,欢迎大佬指出不当之处!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

sqlhelper集成dynamic多数据源的分页问题(非教学向) 的相关文章

随机推荐

  • 《Centos7——实战-完全备份和增量备份》

    目录 完全备份和增量备份 1 需要开启log bin日志 2 增量和全备脚本 3 计划任务 模拟数据丢失 1 新增数据 2 数据备份 3 删除数据 4 数据的恢复 完全备份和增量备份 一般都三种备份种类 完全备份 差异备份 增量备份 完全备
  • Android中的延时工作队列——WorkQueue教程

    Android中的延时工作队列 WorkQueue教程 工作队列是Android开发中常用的一种机制 它允许我们按照一定的顺序和延时执行任务 在本教程中 我们将介绍如何使用Android的WorkQueue来创建延时工作队列 并提供相应的源
  • 云计算————系统部署

    云计算基础篇 前言 云计算 cloud computing 是基于互联网的相关服务的增加 使用和交付模式 通常涉及通过互联网来提供动态易扩展且经常是虚拟化的资源 云是网络 互联网的一种比喻说法 过去在图中往往用云来表示电信网 后来也用来表示
  • hibernate的insert数据正常,但是update数据乱码问题解决

    在做项目是发现 hibernate的insert数据正常 但是update数据是却出现乱码 解决办法 在tomcat的conf server xml中找到下面代码的位置
  • Java JUnit 单元测试小结

    测试类型 单元测试 Unit test 单元测试关注单一的类 它们存在的目的是检查这个类中的代码是否按照期望正确运行 集成测试 Integration test 集成测试是检查开发的模块和其他模块整合时是否正常工作 虽然集成测试的代码影响范
  • 【JavaScript基础】你真正了解如今的Js数组吗,看这篇就(Go)够了

    JavaScript基础 你真正了解如今的Js数组吗 看这篇就 Go 够了 博客说明 文章所涉及的部分资料来自互联网整理 当然还有自己个人的总结和看法 分享的目的在于共建社区和巩固自己 引用的资料如有侵权 请联系本人删除 幸好我在 感谢你来
  • 虚拟化原理之KVM

    2 1 kvm技术基础 KVM kernel based virtual machine 的名字 基于kernel的虚拟机 已经很准确的说出了kvm的设计思路 也就是依赖linux内核 完全利用linux内核来实现cpu的调度 内存管理的功
  • laravel 简介

    Laravel是一款基于MVC设计模式的PHP框架 提供了一系列便捷的API接口 包括数据库 路由 表单验证等等 使PHP开发更为快速和优雅 一言以蔽 Laravel为WEB艺术家而生 1 安装 先保证你已经安装好了PHP 接下来 你可以直
  • 调试osgEarth(三十三)分页瓦片卸载器子节点的作用--(3)渲染遍历的帧号和时间设置-TerrainCuller类 的构造函数--visitorData

    继续调试 每天调试一点点 又不累 又能够细品 这里似乎是存储visitorData临时数据的东东 很明显 这个为空 返回false isSpy false 也就是说visitorData的 dataStore里面的 table里面不存在cu
  • 毕设:基于CNN卷积神经网络的猫狗识别、狗品种识别(Tensorflow、Keras、Kaggle竞赛)

    基于卷积神经网络的图像识别算法及其应用研究 毕业快一年了 拿出来分享给大家 我和网上唯一的区别就是 我能够同时实现两个方案 猫狗识别和狗品种识别 我当时也是网上各种查 花了2 3个月的时间 一个萝卜一个坑走过来的 深度学习真的是深似海呀 不
  • 梅森素数(C语言求解)

    梅森数 Mersenne Prime 指的是形如 1的正整数 其中指数 n 是素数 如果一个梅森数是素数 则称其为梅森素数 另外 由因式分解法可以证明 如果 1 是素数 则 n 也一定是素数 例如 当 n 2 3 5 7 时 1 都是素数
  • 基于径向基神经网络RBF多输入多输出预测,RBF多变量回归预测,matlab代码。评价指标包括:R2、MAE、MSE、RMSE和MAPE等,代码质量极高,方便学习和替换数据。

    清空环境变量 warning off 关闭报警信息 close all 关闭开启的图窗 clear 清空变量 clc 清空命令行 导入数据 res xlsread 数据 xlsx 数据分析 num size 0 8 训练集占数据集比例 ou
  • AI新阶段:认知智能加速工业制造智能转型

    作者 工业互联网周刊 周宝冰 伴随全球数字化进程加快 人工智能技术与产业融合程度逐渐加深 能思考 会判断 的认知智能技术逐步应用于智能客服 智能推荐 智能营销 智能分析等诸多场景 不断释放产业应用价值 近期 华院计算技术 上海 股份有限公司
  • Centos 7安装Harbor

    Harbor 对于docker版本及docker compose版本有要求 根据需要安装 一 Docker搭建 安装最新版 1 安装docker wget qO https get docker com sh 2 配置加速器 cd etc
  • 关于脚本中使用nohup启动项目的问题

    1 在Jenkins中配置了sh home dubbo service bin start sh 使用以下脚本 usr bin env bash 省略 nohup java JAVA OPTS JAVA MEM OPTS JAVA DEBU
  • 小程序中关于红包雨的实现

    一 原型依据 在我这个项目中小程序端所需要实现的只有红包雨的下落动画和通屏背景图的兼容 关于红包点击金额的计算是由后端实现的 首先来看下需要实现的效果图 二 实现代码 首先是第一次进入的页面 在这个页面的时候会进行静默登录 静默登录成功的话
  • webpack : 无法加载文件 C:\Program Files\nodejs\webpack.ps1

    webpack 无法加载文件 C Program Files nodejs webpack ps1 1 问题 2 解决办法 1 问题 使用webpack打包是报错如下 webpack 无法加载文件 C Program Files nodej
  • LINUX系统下:Cuda+Cudnn+Tensorflow-GPU环境配置学习总结

    1 cuda cudnn安装 1 1下载cuda 1 1 1查看系统支持的cuda版本 可以安装低于该版本的 不能超过该版本 nvidia smi 1 1 2下载cuda cuda历史版下载 1 2 3安装 1 找到下载的cuda文件所在的
  • CUnit用法总结

    简介 CUnit是一个用C语言写的单元测试库 它是一个简单的测试框架 提供了丰富的断言语句来测试常用的数据类型 此外 对于跑测试用例和反馈测试结果 CUnit都有一些不同的接口 它可以编译成动态库或者静态库 基本框架 CUnit是一个可以跨
  • sqlhelper集成dynamic多数据源的分页问题(非教学向)

    一 问题描述 最近接手 顶锅 了公司的框架维护工作 第一项任务就是集成dynamic多数据源框架 dynamic官方使用文档 本文不是教学 有兴趣的小伙伴可以自己查阅文档 集成dynamic之后 一切都很顺利 但是测试到SQLHelper框