PageHelper开源框架解读

        在使用springboot开发系统时,列表查询经常会用PageHelper来进行分页。使用起来很方便,但从未想过它的实现原理,所以对其进行解读。

@Service
public class ScUserServiceImpl extends ServiceImpl<ScUserMapper, ScUser> implements IScUserService {@Overridepublic PageInfo<ScUser> pageList(UserListF form) {LambdaQueryWrapper<ScUser> qw = Wrappers.<ScUser>lambdaQuery().like(ScUser::getName, form.getName());// 开启分页,对下一条执行的sql进行分页Page<ScUser> page = PageHelper.startPage(form.getPageNum(), form.getPageSize());List<ScUser> userList = baseMapper.selectList(qw);return new PageInfo<>(page);}
}

        基于PageHelper(v5.3.2)官方文档,这是一个最简单、最常用的分页demo,持久层框架使用的是Mybatis-plus.

        调试截图:

        调试过程发现3个问题点:

  1. 为什么调用PageHelper.startPage()方法后可以实现分页?
  2. 为什么在执行sql查询前先执行select count(0) ?
  3. 为什么查询出来的userList不需要return,直接return new PageInfo<>(page)就可以有数据?

        追踪过程:

        进入PageHelper.startPage()方法,看到里面有一个 setLocalPage(page) 方法,方法的入参page里包含了分页参数pageNum、pageSize等

        setLocalPage方法对 LOCAL_PAGE 这个线程局部变量进行进行赋值

        在getLocaPage方法打断点,看什么时候会取出LOCAL_PAGE线程局部变量。最终发现方法落在了com.github.pagehelper.PageHelper#doBoundSql

        同时在该方法的第二个入参boundSql里可以下一条要执行的sql

        继续追踪,看到它的上级调用方法在com.github.pagehelper.PageInterceptor#intercept

         PageInterceptor这个类实现了ibatis的Interceptor接口,从而实现了对sql语句的拦截

        intercept()这个方法的中文注释非常完整,基本可以对照着阅读源码。

        其中 dialect.beforeCount()这个方法会去线程局部变量LOCAL_PAGE中拿到count属性,从而决定是否在分页查询前执行count(0)查询。而这个count属性在一开始我们调用PageHelper.startPage()的时候,就配置了默认值true。

        而 ExecutorUtil.pageQuery() 则是对查询sql进行解析(配置了多种解析器兼容mysql、oracle、sqlserver、Oscar等),并组装成对应的分页sql。组装好的sql将其封装为BoundSql对象,再调用org.apache.ibatis.executor.Executor#query()方法执行,最终拿到分页查询结果。      

        根据现有的结论我们可以得出,分页参数是通过ThreadLocal<Page>的方式传递的,那么第3个问题,为什么分页查询结果集不需要return而是直接return page对象,答案也就水落石出了。

        在分页查询结束后,dialect.afterPage()方法会将结果集resultList塞入到LOCAL_PAGE 这个线程局部变量里去。

        问题点解答:

        1、为什么调用PageHelper.startPage()方法后可以实现分页?

        因为startPage方法将分页参数保存到了线程局部变量,然后通过PageInterceptor(它实现了ibatis提供的inteceptor接口)对下一条即将执行的query sql进行拦截,解析语义并组装为分页query sql,执行并拿到结果集,并存放到线程局部变量里去。

        2、为什么在执行sql查询前先执行select count(0) ?

        因为调用 PageHelper.startPage(form.getPageNum(), form.getPageSize()) 方法时传递了默认count属性值,默认为true,所以在分页时会执行count(0)查询总记录数。它并不影响分页的过程、结果,它只是满足业务需要所做的一个查询。

        如果不需要count(0),可以调用 PageHelper.startPage(form.getPageNum(), form.getPageSize(), false) 来指定。

        3、为什么查询出来的userList不需要return,直接return new PageInfo<>(page)就可以有数据?

        因为page是一个线程局部变量,分页查询结束后,PageInterceptor会调用 dialect.afterPage() 将结果集保存到page里去,所以page里会有数据。

        你也可以return userList,但是page里的属性更加丰富,它除了结果集之外,还有当前页、每页记录数、总记录数等等.....

        小结:

        经过代码追踪,我明白了PageHelper的本质其实是基于ThreadLocal和ibatis提供的sql监听器实现的,解开了这层神秘的面纱。这种对sql约定好的的统一处理策略,非常值得学习。对也让我对mybatis的的执行过程更加好奇,后续可以更进一步对mybatis的原理进行追踪和理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/713592.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WIN10 无密码自动登录

1、家里重装了一下WIN10系统&#xff0c;第一次登陆居然用了微软网站账号&#xff0c;结果密码忘记了&#xff0c;后面只能用PIN码登陆系统。 2、需要登录微软的网站修改密码&#xff1a; Microsoft account | Sign In or Create Your Account Today – Microsoft 3、在运行…

APP自动化测试-入门示例

入门示例 通过上一篇博客APP自动化测试介绍-CSDN博客的学习&#xff0c;相信大家对APP自动化测试已经有了一定的了解&#xff0c;下面演示一下入门示例 1. 配置Appium 1.1. 点击Appium图标&#xff0c;打开服务器&#xff1a; 1.2. 点击Edit Configurations,进入配置页面&am…

【LeetCode】【滑动窗口长度不固定】978 最长湍流子数组

1794.【软件认证】最长的指定瑕疵度的元音子串 这个例题&#xff0c;是滑动窗口中长度不定求最大的题目&#xff0c;在看题之前可以先看一下【leetcode每日一题】【滑动窗口长度不固定】案例。 题目描述 定义&#xff1a;开头和结尾都是元音字母&#xff08;aeiouAEIOU&…

GIT基本的命令

文章目录 04.GIT本地操作-初始化工作区内容小结 05.GIT本地操作-add与commit目标内容小结 06.GIT本地操作-差异比较目标内容小结 07.GIT本地操作-版本回退目标内容小结 08.GIT本地操作-修改撤消目标内容小结 09.GIT本地操作-总结 04.GIT本地操作-初始化工作区 内容 初始化工作…

Java对象大小计算

概述 在实际应用中&#xff0c;尤其是在进行JVM调优时&#xff0c;理解并正确估计对象大小是非常重要的&#xff0c;因为这直接影响到内存分配、垃圾回收效率以及应用程序的整体性能。 对象的组成 在Java中&#xff0c;计算一个对象的大小是为了了解它在内存中占用的确切空间…

第十五天-爬虫项目实战

目录 1.介绍 2.代码 1.main.py 2.PageSider.py 3.DetailSpider.py 4.DataParse.py 5.Constant.py 6.HanderRequest.py 1.介绍 1. 使用多线程爬取网站 2.爬取数据后保存至excel 3.爬取网站(仅做测试)网创类项目爬取&#xff1a;https://www.maomp.com/ 4..实现效果 …

元数据优化:提升您的网站在搜索引擎中的表现

前言 在之前的文章中&#xff0c;我们探讨了如何通过超链接来提高用户在网站的使用体验。本篇将聚焦于元数据的优化&#xff0c;揭示它如何成为提升网站曝光率和点击率的秘密武器。 一、介绍 元数据&#xff0c;或称之为数据的数据&#xff0c;在网页开发中占据着不可忽视的角…

IPD MM流程之业务策略工具:安索夫矩阵

IPD市场管理流程&#xff0c;华为内部称为“MM流程”&#xff08;Market Management&#xff0c;MM&#xff09;。华为市场管理是通过对市场和细分市场的分析&#xff0c;制定细分市场的策略&#xff0c;形成商业计划&#xff0c;把商业计划落实在日常工作当中。MM流程其中一个…

git根据文件改动将文件自动添加到缓冲区

你需要修改以下脚本中的 use_cca: false 部分 #!/bin/bash# 获取所有已修改但未暂存的文件 files$(git diff --name-only)for file in $files; do# 检查文件中是否存在"use_cca: false"if grep -q "use_cca: false" "$file"; thenecho "Ad…

qt5-入门-使用拖动方式创建Dialog

参考&#xff1a; C GUI Programming with Qt 4, Second Edition 本地环境&#xff1a; win10专业版&#xff0c;64位&#xff0c;Qt5.12 目录 实现效果基本流程逐步实操1&#xff09;创建和初始化子部件2&#xff09;把子部件放进布局中3&#xff09;设置tab顺序4&#xff09…

jstat命令查看jvm的GC信息

文章目录 前言jstat命令查看jvm的GC信息1. 概述2. 应用堆内存水位阀值大小怎么确定3. 使用 jps 命令查看 Java 进程的进程号&#xff08;PID&#xff09;![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/5097401443314e9d808a83b694dbc6e5.png)4. jstat用法5. 类加载…

UE4 Niagara 关卡3.1官方案例解析二

自己尝试做做&#xff0c;打乱顺序 1、新建空的niagara system&#xff0c;添加空的发射器。更换渲染器为网格体渲染器并添加网格体。 2、发射器更新里面添加Spawn Rate&#xff0c;发射个粒子看看 效果图&#xff1a; 3、采样静态网格体&#xff0c;网格体粒子出生于静态网格…

【排序算法】基数排序

一&#xff1a;基本概念 1.1 基数排序(桶排序)介绍 基数排序&#xff08;radix sort&#xff09;属于“分配式排序”&#xff08;distribution sort&#xff09;&#xff0c;又称“桶子法”&#xff08;bucket sort&#xff09;或bin sort&#xff0c;顾名思义&#xff0c;它是…

【图说】电脑发展史

免责声明:文中有一些图片来源自网络,如有版权请通知我删除,谢谢! “结绳记事”是计算的开端 如果说“结绳记事”仅是计数,那么“算筹”就是真正的计算工具 算盘也是我们老祖宗的杰出发明,最擅长“加减乘除”,包括但不限于乘方、开方、对数等。还能进行开发智力的“珠心算…

鼠标失灵怎么办?电脑出现鼠标失灵的详细处理方法介绍

无论是笔记本电脑还是台式机电脑&#xff0c;鼠标是必不可少的外设之一&#xff0c;而我们在使用电脑的过程中&#xff0c;经常回遇到鼠标突然失灵了&#xff0c;不听使唤&#xff0c;控制不了&#xff0c;接下小编来与大家一起分享&#xff0c;遇到这种情况我们该怎么办 有时…

C语言学习笔记(二)

C语言学习 学习笔记(一) 学习笔记(二&#xff09; 文章目录 C语言学习一、C语言中的数据类型进制二进制八进制十六进制进制转换表 单位换算寻址 数据类型基本类型整数类型整数的有符号和无符号实数类型字符型 构造类型指针类型空类型总结 常量直接常量符号常量转义符 符号常量…

Python并发编程:多线程-GIL全局解释器锁

一 引子 在Cpython解释器中&#xff0c;同一个进程下开启的多线程&#xff0c;同一时刻只能有一个线程执行&#xff0c;无法利用多核优势首先&#xff1a;需要明确的一点是GIL并不是Python的特性&#xff0c;它是在实现Python解析器(CPython)时所引入的一个概念。就好比c是一套…

协议(网络协议)

HTTP/HTTPS 协议 HTTP 实际上是个缩写&#xff0c;英文全称是&#xff1a;Hyper Text Transfer Protocol &#xff08;超文本传输协议&#xff09;。 最常用的网页&#xff08;也叫web页&#xff09;就是一种超文本的具体表现形式。HTTPS &#xff08;全称&#xff1a;Hyper …

ICASSP2024 | ICMC-ASR 车载多通道语音识别挑战赛总结

为促进驾驶场景中语音处理和识别研究&#xff0c;在ISCSLP 2022上成功举办智能驾驶座舱语音识别挑战 (ICSRC)的基础上&#xff0c;西工大音频语音与语言处理研究组 (ASLPNPU)联合理想汽车、希尔贝壳、WeNet社区、字节、微软、天津大学、南洋理工大学以及中国信息通信研究院等多…

EMO在哪体验?阿里对口型视频生成工具EMO下载地址?阿里巴巴新模型EMO的技术原理

这几天&#xff0c;阿里的对口型视频生成工具EMO火了。根据官方宣传&#xff0c;EMO只需要上传一张图片和一段音频就可以一键生成对口型视频&#xff0c;而且视频中的嘴型还可以与声音匹配。这项技术支持多语言、对话、唱歌以及快速语速的适配&#xff0c;但也可能成为制造虚假…