当前位置: 首页 > 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; 对新认定的国家重点实验室、国家…...

AI IDE CLI:为AI编程助手打造的轻量级本地开发环境

1. 项目概述&#xff1a;一个为AI时代量身定制的本地开发环境CLI工具如果你是一名开发者&#xff0c;最近肯定没少和各类AI编程助手打交道。无论是GitHub Copilot、Cursor&#xff0c;还是各种本地部署的大模型&#xff0c;它们正在深刻地改变我们写代码的方式。但随之而来的一…...

浏览器扩展开发实战:光标交互防火墙的设计与实现

1. 项目概述与核心价值最近在折腾浏览器插件开发&#xff0c;偶然在GitHub上看到了一个名为“Raidu Firewall Cursor Extension”的项目。光看这个名字&#xff0c;就让我这个对网络安全和效率工具都感兴趣的老码农眼前一亮。这玩意儿本质上是一个浏览器扩展&#xff0c;但它把…...

claw-diary:基于Git与Markdown的开发者命令行日记工具

1. 项目概述&#xff1a;一个面向开发者的命令行日记工具最近在折腾个人知识管理&#xff0c;发现市面上的日记软件要么太重&#xff0c;要么太花哨&#xff0c;要么就是数据被锁在云端&#xff0c;让人不太放心。作为一个常年与终端为伴的开发者&#xff0c;我一直在想&#x…...

AI技能白日梦:让大模型通过自主推演实现能力进化

1. 项目概述&#xff1a;当AI学会“白日做梦”最近在GitHub上看到一个挺有意思的项目&#xff0c;叫regiep4/skill-daydreaming。光看这个名字&#xff0c;就让人浮想联翩——“技能白日梦”&#xff1f;这听起来不像是一个传统的工具库或者框架&#xff0c;更像是一种对AI能力…...

PlayAI多语种翻译能力边界实测(含方言识别、专业术语库热加载、混合语种断句逻辑),你敢信它已通过ISO/IEC 24615标准认证?

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;PlayAI多语种同步翻译功能详解 PlayAI 的多语种同步翻译功能基于端到端神经机器翻译&#xff08;NMT&#xff09;架构与实时语音流处理引擎深度融合&#xff0c;支持中、英、日、韩、法、西、德、俄等 …...

模型下载与转换实战:从HuggingFace到GGUF/SafeTensors,格式、量化与校验全解析

系列导读 你现在看到的是《本地大模型私有化部署与优化:从入门到生产级实战》的第 2/10 篇,当前这篇会重点解决:让你不再被模型格式和量化选项搞晕,确保下载和转换过程零失败。 上一篇回顾:第 1 篇《本地大模型部署前夜:硬件选型、环境搭建与框架对比(Ollama/vLLM/Lla…...

PyTorch实战:手把手教你处理Mini-ImageNet数据集(附100类标签映射文件)

PyTorch实战&#xff1a;从零构建Mini-ImageNet数据管道与标签映射系统 当你第一次打开Mini-ImageNet的压缩包时&#xff0c;可能会被三个看似友好的CSV文件迷惑——train.csv、val.csv和test.csv。但当你真正尝试用PyTorch加载这些数据时&#xff0c;才会发现它们就像IKEA的组…...

你还在手动写Type Hints和Docstring?Gemini实时生成合规PEP 484/561注释(附GitHub Star超5k的私有化部署模板)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;你还在手动写Type Hints和Docstring&#xff1f;Gemini实时生成合规PEP 484/561注释&#xff08;附GitHub Star超5k的私有化部署模板&#xff09; 现代Python工程已将类型安全与可维护性提升至核心地位…...

当代酷刑:如厕等信号

如厕等信号&#xff0c;属于当代十大酷刑之一。作为社会观察理性分析的结合体&#xff0c;今天&#xff0c;我想写一些这物理世界的墙&#xff0c;也是这消费世界的墙。你有没有过这样的感受&#xff1f;不管你家里换了多么厉害的宽带&#xff0c;多么高端前沿的路由器&#xf…...

黑金AX301开发板+HS-04模块:FPGA超声波测距从原理到数码管显示的保姆级教程

黑金AX301开发板实战&#xff1a;基于HS-04模块的FPGA超声波测距系统设计 当超声波传感器遇到FPGA&#xff0c;我们能创造出怎样的精准测距系统&#xff1f;本文将带你从硬件连接到Verilog编码&#xff0c;完整实现一个基于黑金AX301开发板和HS-04超声波模块的测距系统。不同于…...