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

MyBatis-PageHelper 源码解说

归档

  • GitHub: MyBatis-PageHelper-源码解说

总说明

  • 源码仓库: https://github.com/pagehelper/Mybatis-PageHelper
  • 克隆:git clone https://github.com/pagehelper/Mybatis-PageHelper.git
  • 切分支(tag):git checkout master
  • JDK: 17

单元测试

  • 参考:com.github.pagehelper.test.reasonable.PageTest
    @Testpublic void testMapperWithStartPage() {SqlSession sqlSession = MybatisReasonableHelper.getSqlSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);try {// PageHelper.startPage(20, 50);    // 超出总页数时,会自动改为查询最后一页PageHelper.startPage(4, 50);                // 开启分页,ref: sign_m_110List<User> list = userMapper.selectAll();   // 分页拦截,ref: sign_m_210PageInfo<User> page = new PageInfo<User>(list);}}
  • hsqldb\mybatis-config-reasonable.xml
<configuration><plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"><property name="reasonable" value="true"/></plugin></plugins>
</configuration>
  • UserMapper.xml
<mapper namespace="com.github.pagehelper.mapper.UserMapper"><select id="selectAll" resultType="User">select * from user order by id -- comment</select>
</mapper>

原理

开启分页

  • com.github.pagehelper.PageHelper
// sign_c_010
public class PageHelper extends PageMethod implements Dialect, BoundSqlInterceptor.Chain {// sign_m_010  后处理@Overridepublic void afterAll() {// 这个方法即使不分页也会被执行,所以要判断 nullAbstractHelperDialect delegate = autoDialect.getDelegate();if (delegate != null) {delegate.afterAll();autoDialect.clearDelegate();}clearPage();    // 移除本地变量,ref: sign_m_011}// sign_m_011  移除本地变量public static void clearPage() {LOCAL_PAGE.remove();}
}
  • com.github.pagehelper.page.PageMethod
public abstract class PageMethod {protected static final ThreadLocal<Page> LOCAL_PAGE    = new ThreadLocal<Page>();protected static       boolean           DEFAULT_COUNT = true;// sign_m_110 开启分页public static <E> Page<E> startPage(int pageNum, int pageSize) {return startPage(pageNum, pageSize, DEFAULT_COUNT); // 默认进行 COUNT(0) 查询}public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count) {return startPage(pageNum, pageSize, count, null, null);}public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {Page<E> page = new Page<E>(pageNum, pageSize, count);page.setReasonable(reasonable);     // 分页合理化设置page.setPageSizeZero(pageSizeZero); // true 且 pageSize = 0 时返回全部结果,false 时分页...setLocalPage(page);return page;}public static void setLocalPage(Page page) {LOCAL_PAGE.set(page);}
}

拦截器

  • com.github.pagehelper.PageInterceptor
@Intercepts({// 设置对目标接口和目标 (指定的方法名和参数类型) 方法进行拦截@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
})
public class PageInterceptor implements Interceptor {private volatile     Dialect    dialect;private              String     default_dialect_class = "com.github.pagehelper.PageHelper";@Override // 初始化 dialectpublic void setProperties(Properties properties) {...String dialectClass = ... default_dialect_class;    // 用默认的Dialect tempDialect = ClassUtil.newInstance(dialectClass, properties);tempDialect.setProperties(properties);...// 初始化完成后再设置值,保证 dialect 完成初始化。// 默认情况下,dialect 是 PageHelper 实例,ref: sign_c_010dialect = tempDialect;}// sign_m_210 分页拦截@Overridepublic Object intercept(Invocation invocation) throws Throwable {try {Object[] args = invocation.getArgs();MappedStatement ms = (MappedStatement) args[0];...if (args.length == 4) { // 4 个参数时...} else {                // 6 个参数时...}...List resultList;if (!dialect.skip(ms, parameter, rowBounds)) { // 需要分页...// 判断是否需要进行 count 查询if (dialect.beforeCount(ms, parameter, rowBounds)) {... // 异步 Count 处理else {// 查询总数,将原接口改成 COUNT(0) 统计 SQL 再进行查询Long count = count(executor, ms, parameter, rowBounds, null, boundSql);// 处理查询总数,返回 true 时继续分页查询,false 时直接返回if (!dialect.afterCount(count, parameter, rowBounds)) { // 将 count 设置到 Page 里面去// 当查询总数为 0 时,直接返回空的结果return dialect.afterPage(new ArrayList(), parameter, rowBounds);}}}resultList = ExecutorUtil.pageQuery( // 将原 SQL 改成分页 SQL,再执行查询dialect, executor, ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);... // 异步 Count 处理} ... // else: 不分页,直接查询结果return dialect.afterPage(resultList, parameter, rowBounds); // 将 list 添加到 Page,并返回 Page 对象} finally {if (dialect != null) {dialect.afterAll(); // 清除线程变量。ref: sign_m_010}}}
}

总结

  • 原理总体较简单
  • 只在一个拦截器里处理(统计与数据查询)
  • 最后返回 Page<T> 封装集合类

相关文章:

MyBatis-PageHelper 源码解说

归档 GitHub: MyBatis-PageHelper-源码解说 总说明 源码仓库&#xff1a; https://github.com/pagehelper/Mybatis-PageHelper克隆&#xff1a;git clone https://github.com/pagehelper/Mybatis-PageHelper.git切分支&#xff08;tag&#xff09;&#xff1a;git checkout m…...

基于uni-app和图鸟UI的智慧校园圈子小程序开发实践

摘要&#xff1a; 随着教育信息化和“互联网教育”的快速发展&#xff0c;智慧校园建设已成为推动校园管理现代化、提高教育教学质量的重要手段。本文介绍了基于uni-app和图鸟UI开发的智慧校园圈子小程序&#xff0c;旨在通过一站式服务、个性化定制、数据互通和安全可靠等特点…...

STM32 keil工程移植到Visual Studio Code环境中编译

1、GCC Vscode 搭建 STM32 开发环境 GCC Vscode 搭建 STM32 开发环境&#xff08;一&#xff09;- 环境部署 - 知乎 (zhihu.com) 2、在原有keil工程下找到原本CUBEMX生成的.ioc工程文件 3、将.ioc文件复制一个新的文件夹下双击打开工程&#xff0c;将IDE选为Makefile&…...

细说CountDownLatch

CountDownLatch是Java中提供的一个同步辅助类&#xff0c;它允许一个或多个线程等待其他线程完成操作。在面试中&#xff0c;面试官经常会询问候选人是否在实际项目中使用过CountDownLatch&#xff0c;以评估其对多线程编程和并发控制的理解和经验。本文将详细介绍CountDownLat…...

java-克隆应用

5.2 创建复杂对象 对于某些复杂对象&#xff0c;通过克隆来创建其副本比通过构造函数创建新实例更加高效。例如&#xff0c;当对象包含大量字段或需要进行复杂初始化时&#xff0c;克隆可以显著提高性能。 java 复制代码 class ComplexObject implements Cloneable { private …...

RPC协议

3.8 既然有 HTTP 协议&#xff0c;为什么还要有 RPC 假设我们需要在 A 电脑的进程发一段数据到 B 电脑的进程&#xff0c;我们一般会在代码里使用 Socket 进行编程。 这时候&#xff0c;我们可选项一般也就 TCP 和 UDP 二选一。TCP 可靠&#xff0c;UDP 不可靠。 类似下面这…...

医疗器械3D全景展会在线漫游创造数字化时代的展览新篇章

在数字化浪潮的引领下&#xff0c;VR虚拟网上展会正逐渐成为企业展示品牌实力、吸引潜在客户的首选平台。我们与广交会携手走过三年多的时光&#xff0c;凭借优质的服务和丰富的经验&#xff0c;赢得了客户的广泛赞誉。 面对传统展会活动繁多、企业运营繁忙的挑战&#xff0c;许…...

IP_Endpoint类型在CAPL中的使用

在使用TCP/IP协议栈通信时,创建Socket套接字调用接口函数实现通信的整个过程成为一种主流且便捷的方式。在CAPL中,Client需要创建TCP或UDP套接字,绑定自己的IP地址和一个端口号,作为自己的通信端点。 on key c {clientsocket = tcpOpen(ipGetAddressAsNumber("192.16…...

数据资产与用户体验优化:深入挖掘用户数据,精准分析用户需求与行为,优化产品与服务,提升用户体验与满意度,打造卓越的用户体验,赢得市场认可

一、引言 在数字化时代&#xff0c;数据已经成为企业最宝贵的资产之一。通过深入挖掘和分析用户数据&#xff0c;企业能够精准把握用户需求和行为&#xff0c;从而优化产品与服务&#xff0c;提升用户体验和满意度。这不仅有助于企业在激烈的市场竞争中脱颖而出&#xff0c;还…...

基于TCAD与紧凑模型结合方法探究陷阱对AlGaN/GaN HEMTs功率附加效率及线性度的影响

来源&#xff1a;Investigation of Traps Impact on PAE and Linearity of AlGaN/GaN HEMTs Relying on a Combined TCAD–Compact Model Approach&#xff08;TED 24年&#xff09; 摘要 本文提出了一种新型建模方法&#xff0c;用于分析GaN HEMTs的微波功率性能。通过结合工…...

具身智能概念

具身智能作为人工智能发展的一个重要分支&#xff0c;伴随着大模型技术的爆发与硬件成本的降低&#xff0c;即软硬件技术走向成熟&#xff0c;正在成为广泛关注的热门&#xff0c;一时之间&#xff0c;具身智能机器人也成为了科技界新的风向标。 什么是具身智能&#xff1f; …...

C++ 43 之 自增运算符的重载

#include <iostream> #include <string> using namespace std;class MyInt{friend ostream& operator<< (ostream& cout , MyInt& int1); public:MyInt(){this->m_num 0;}// 前置自增&#xff1a; 成员函数实现运算符的重载 返回的是 引用&a…...

计算机网络:1概述、2物理层

目录 概述因特网网络、互连网&#xff08;互联网&#xff09;与因特网的区别与关系因特网发展的三个阶段因特网服务提供者&#xff08;Internet Service Provider&#xff0c;ISP&#xff09;因特网的标准化工作因特网的管理结构 三种交换电路交换分组交换报文交换 计算机网络性…...

【Ardiuno】实验使用ESP32接收电脑发送的串口数据(图文)

使用ESP32可以非常方便的与电脑进行串口通讯&#xff0c;一般我们可以用串口接收ESP32的输出作为调试使用&#xff0c;今天我们再来实验一下从电脑端向ESP32单片机发送数据。 发送数据程序代码&#xff1a; void setup() {Serial.begin(9600); }void loop() { if(Serial.ava…...

思科ospf+rip重发布配置命令

——————————————————————————————————————————— 基础配置 R1 Router>en #进入配置模式 Router#conf #进入配置模式 Router(config)#h…...

椭圆的矩阵表示法

椭圆的矩阵表示法 flyfish 1. 标准几何表示法 标准几何表示法是通过椭圆的几何定义来表示的&#xff1a; x 2 a 2 y 2 b 2 1 \frac{x^2}{a^2} \frac{y^2}{b^2} 1 a2x2​b2y2​1其中&#xff0c; a a a 是椭圆的长半轴长度&#xff0c; b b b 是椭圆的短半轴长度。 2.…...

智慧乡村和美人家信息化系统

一、简介 智慧乡村和美人家信息化系统是一个综合管理平台&#xff0c;集成了首页概览、一张图可视化、数据填报、智能评估、便捷申报、公开公示、任务管理、活动发布和灵活配置等功能。该系统不仅提升了乡村管理效率&#xff0c;也优化了家庭生活的便捷性。通过一张图&#xf…...

ios-deploy - Required for installing your app on a physical device with the CLI

ios-deploy 是一个用于在 iOS 设备上安装、调试和运行 iOS 应用的开源工具。如果你正在使用命令行界面&#xff08;CLI&#xff09;来部署 React Native 或其他原生 iOS 应用到物理设备&#xff0c;那么安装 ios-deploy 是必要的。 以下是安装 ios-deploy 的一般步骤&#xff…...

thinkphp5使用模型删除与复杂查询EXP

模型删除 应用软删除 表中需要有字段&#xff0c;deletetime 模型中使用下面方法 use SoftDelete;protected $deleteTime delete_time;真实删除 // 软删除 User::destroy(1); // 真实删除 User::destroy(1,true); $user User::get(1); // 软删除 $user->delete(); // 真…...

铜陵市省重点实验室、省工程技术研究中心认定奖励补贴和申报认定条件流程归集

本文介绍铜陵市省重点实验室、省工程技术研究中心认定奖励补贴和申报认定条件等内容&#xff0c;详情如下&#xff0c;需要申报的可指导&#xff01; 铜陵市省重点实验室、省工程技术研究中心认定奖励补贴&#xff08;2023年发布&#xff09; 对新认定的国家重点实验室、国家…...

2026年华为云OpenClaw如何安装?配置百炼API零门槛10分钟步骤

2026年华为云OpenClaw如何安装&#xff1f;配置百炼API零门槛10分钟步骤。OpenClaw&#xff08;曾用名Clawdbot&#xff09;是一款轻量化、可扩展的开源AI智能体执行框架&#xff0c;支持自然语言指令驱动、多模型灵活切换与全场景任务自动化。对于新手而言&#xff0c;阿里云轻…...

如何用StreamCap实现多平台直播内容的自动捕获与管理

如何用StreamCap实现多平台直播内容的自动捕获与管理 【免费下载链接】StreamCap Multi-Platform Live Stream Automatic Recording Tool | 多平台直播流自动录制客户端 基于FFmpeg 支持监控/定时/转码 项目地址: https://gitcode.com/gh_mirrors/st/StreamCap 在数字…...

Unpaywall扩展:一键解锁学术论文的终极免费方案

Unpaywall扩展&#xff1a;一键解锁学术论文的终极免费方案 【免费下载链接】unpaywall-extension Firefox/Chrome extension that gives you a link to a free PDF when you view scholarly articles 项目地址: https://gitcode.com/gh_mirrors/un/unpaywall-extension …...

大多数人手动给Agent加记忆 Meta HyperAgents却让AI自己发明了完整记忆系统

你是不是也这样造Agent&#xff1a;先搭好任务执行模块&#xff0c;再手动塞一个向量数据库或RAG当记忆&#xff0c;最后发现跨轮迭代时效果还是“每次从零开始”&#xff1f;性能没 compounding&#xff0c;跨任务迁移更是一团乱麻。明明AI已经能自我迭代了&#xff0c;为什么…...

CCC数字钥匙Release 3实战:如何用BLE/UWB实现无钥匙进入(附避坑指南)

CCC数字钥匙Release 3实战&#xff1a;BLE/UWB无钥匙进入系统开发全解析 当你的手机靠近车辆时&#xff0c;车门自动解锁——这种科幻般的体验正通过CCC数字钥匙Release 3标准变为现实。作为汽车电子工程师&#xff0c;我曾用nRF5340开发板搭配UWB模块完整实现了这套系统&#…...

GLM-4.6V-Flash-WEB新手入门:从镜像加速到网页推理实战

GLM-4.6V-Flash-WEB新手入门&#xff1a;从镜像加速到网页推理实战 1. 为什么选择GLM-4.6V-Flash-WEB 智谱AI最新开源的GLM-4.6V-Flash-WEB是一款专为实际业务场景优化的多模态视觉大模型。它结合了视觉理解和语言生成能力&#xff0c;特别适合需要快速部署的Web应用场景。 …...

HiOmics平台:零代码实现ChIP-Seq数据可视化与深度解析

1. 为什么科研人员需要零代码ChIP-Seq分析工具 做表观遗传学研究的朋友们应该都深有体会&#xff0c;ChIP-Seq数据分析就像一场马拉松——从原始数据清洗、序列比对、peak calling到功能注释&#xff0c;每个环节都需要不同的工具和脚本。我刚开始接触这个领域时&#xff0c;光…...

新手最值得入的一款ai音乐工具

2026年&#xff0c;ai音乐爆发的一年。国内国外各种AI音乐工具层出不穷。想要尝试AI音乐的新手宝宝该怎么去选择呢&#xff1f;市面上大大小小的ai音乐创作软件我基本都尝试过。我觉得只有一款工具是最值得推荐的&#xff0c;也是我使用的最多的。那就是蘑兔AI&#xff0c;你们…...

私域数据安全与合规——企微引流必须注意的5个技术红线

做公域引流到企微&#xff0c;数据安全和合规是技术团队必须重视的问题。一旦踩红线&#xff0c;轻则功能受限&#xff0c;重则企微封禁甚至法律风险。今天梳理5个技术红线及应对方案。红线1&#xff1a;用户隐私数据存储企微API返回的用户信息包含ExternalUserID&#xff08;外…...

10分钟掌握全网资源下载神器:res-downloader从入门到精通

10分钟掌握全网资源下载神器&#xff1a;res-downloader从入门到精通 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader 你是否遇…...