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

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...