当前位置: 首页 > news >正文

【12.MyBatis源码剖析与架构实战】19.MyBatis分⻚插件设计与实战

MyBatis 分页插件设计与实战(完整实操案例)

分页查询是业务系统中最常见的需求之一。虽然可以手动在 SQL 后拼接LIMITROWNUM,但这样会侵入业务代码,且需要为每个查询编写重复的分页逻辑。通过 MyBatis 插件机制,我们可以实现一个透明物理分页插件:开发者只需在调用 Mapper 方法前设置分页参数,插件自动拦截 SQL 并改写为对应数据库的分页语句,同时返回总记录数。


一、需求分析

功能点说明
透明分页无需修改原有 Mapper 接口和 XML,只需在 Service 层设置分页参数
物理分页使用数据库方言(LIMIT/ROWNUM/OFFSET FETCH)实现真分页
自动查询总数执行分页查询时自动生成COUNT(*)SQL 并查询总记录数
方言适配支持 MySQL、PostgreSQL、Oracle、SQL Server 等
返回结果返回包含分页信息(总条数、当前页、每页大小)和数据的统一对象

二、设计思路

基于 MyBatis 插件机制,拦截Executor.query方法(因为所有查询最终都会经过它)。核心步骤如下:

  1. 定义分页参数对象Page:存储当前页码、每页大小、总记录数、排序字段等。
  2. 定义方言接口Dialect:提供getCountSql(生成计数 SQL)和getPageSql(生成分页 SQL)方法。
  3. 实现各数据库方言:MySQL、Oracle、PostgreSQL 等。
  4. 编写分页拦截器PageInterceptor
    • 通过@Intercepts注解拦截Executor.query方法。
    • 判断参数中是否包含Page对象,若无则直接放行。
    • 若有,则:
      • 通过反射获取原始的MappedStatementBoundSql
      • 生成并执行 COUNT SQL,获取总记录数并设置到Page对象中。
      • 生成分页 SQL,替换原有BoundSql中的 SQL,并继续执行查询。
      • 将查询结果封装到Page对象中返回。
  5. 使用ThreadLocal传递分页参数:实现线程安全的分页参数传递,避免侵入方法签名。

三、完整源码实现

3.1 分页参数对象Page.java
packagecom.example.plugin.page;importjava.io.Serializable;importjava.util.List;publicclassPage<T>implementsSerializable{privatestaticfinallongserialVersionUID=1L;// 当前页码privateintpageNum=1;// 每页条数privateintpageSize=10;// 总记录数privatelongtotal=0;// 总页数privateintpages=0;// 查询结果集privateList<T>list;// 是否查询总数(默认 true)privatebooleancount=true;// 排序字段(可选,用于简化)privateStringorderBy;publicPage(){}publicPage(intpageNum,intpageSize){this.pageNum=pageNum;this.pageSize=pageSize;}// getter / setter 省略}
3.2 方言接口Dialect.java
packagecom.example.plugin.dialect;publicinterfaceDialect{/** * 根据原始 SQL 生成计数 SQL * @param originalSql 原始查询 SQL * @return 计数 SQL */StringgetCountSql(StringoriginalSql);/** * 根据原始 SQL 和分页参数生成分页 SQL * @param originalSql 原始查询 SQL * @param offset 起始行(从0开始) * @param limit 每页条数 * @return 分页 SQL */StringgetPageSql(StringoriginalSql,intoffset,intlimit);}
3.3 MySQL 方言实现MySQLDialect.java
packagecom.example.plugin.dialect;publicclassMySQLDialectimplementsDialect{@OverridepublicStringgetCountSql(StringoriginalSql){// 简单的 SELECT COUNT(*) 包装,实际需处理 ORDER BY、DISTINCT 等return"SELECT COUNT(*) FROM ("+originalSql+") AS tmp_count";}@OverridepublicStringgetPageSql(StringoriginalSql,intoffset,intlimit){returnoriginalSql+" LIMIT "+offset+", "+limit;}}
3.4 Oracle 方言实现OracleDialect.java
packagecom.example.plugin.dialect;publicclassOracleDialectimplementsDialect{@OverridepublicStringgetCountSql(StringoriginalSql){return"SELECT COUNT(*) FROM ("+originalSql+")";}@OverridepublicStringgetPageSql(StringoriginalSql,intoffset,intlimit){intstartRow=offset+1;intendRow=offset+limit;StringBuildersql=newStringBuilder();sql.append("SELECT * FROM (SELECT TMP_PAGE.*, ROWNUM PAGE_ROW_NUM FROM (");sql.append(originalSql);sql.append(") TMP_PAGE WHERE ROWNUM <= ").append
http://www.jsqmd.com/news/673798/

相关文章:

  • 拆解网红小风扇:它的‘边充边放’和‘过路保护’是怎么用一颗FS8A15S8 MCU实现的?
  • OSG+Qt实战:从官方osgviewerQt例子到自定义3D编辑器界面
  • Typora+LaTeX公式保姆级教程:从基础语法到复杂矩阵排版
  • 避坑指南:YOLOv5 v6.2训练分类模型时,关于数据集划分、种子复现和模型导出的几个关键细节
  • CarMaker for Simulink联合仿真实战:如何利用IPGMovie和Data Inspector实时调试你的车辆模型
  • 必看!2026有自主研发技术的GEO服务商推荐,避开外包坑 - 品牌测评鉴赏家
  • 保姆级教程:用Python和Basemap绘制台风‘利奇马’期间的卫星云图(附完整代码)
  • 用Arduino Nano和AD8232模块DIY一个心率监测手环(附完整代码与电路图)
  • 收藏!AI入行指南:小白程序员必备的岗位选择、技能树与学习路径
  • 终极跨平台RGB灯光控制:OpenRGB一站式解决方案彻底告别软件混乱
  • JavaScript的Object.hasOwn:比hasOwnProperty更安全的属性检查
  • 手机变随身Linux服务器:用Termux+Ubuntu搭建个人网盘/博客的踩坑实录
  • idea 插件envfile初体验
  • 如何快速实现音频转文字:免费开源工具完整指南
  • CityEngine规则文件(.cga)完全解读:从‘看不懂’到能改‘屋顶样式’和‘楼层高度’
  • 无线调试中的端口转发问题
  • 解码CAN总线数据帧:从帧起始到帧结束的逐段精讲
  • 剖析 Sa-Token 权限认证:从注解到拦截器的完整调用链路
  • qemu基础-xml详解
  • Qwen2.5-VL-7B-Instruct部署避坑指南:显存不足报错、端口冲突、路径权限问题汇总
  • 自媒体人,别再纠结文笔了,读者想看的是“解决方案”
  • Dev-C++也能做图形界面?用C++写一个带界面的五子棋对战程序(含AI人机对战)
  • 别再搞混了!STSW-LINK004/007/009到底该用哪个?一张图帮你选对ST-Link工具
  • 超越风险比:用R语言RMST重新审视临床生存数据,以肝硬化研究为例
  • 从Docker到Kubernetes:深入理解容器资源限制背后的systemd cgroups机制
  • 蓝队视角:彻底理解PTH/PTK/PTT,手把手配置检测与防御规则(含Sigma/YARA)
  • 告别黑屏:手把手教你用C语言在Linux下玩转framebuffer画图(附完整代码)
  • Blender3mfFormat插件:3D打印工作流的完整解决方案
  • 避坑指南:在Windows/Mac本地用Diffusers库跑通Stable Diffusion U-Net推理的完整流程
  • Windows平台Termius进阶:从安装激活到个性化汉化实战