PageHelper开源框架解读

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

@Service
public class ScUserServiceImpl extends ServiceImpl<ScUserMapper, ScUser> implements IScUserService {
    @Override
    public 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.mfbz.cn/a/421811.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ABAP - SALV教程02 - 开篇:打开SALV的三种方式之二

全屏模式生成SALV的方式&#xff1a;http://t.csdnimg.cn/CzNLz本文讲解生成可控模式的SALV&#xff0c;该方式需要依赖自己创建屏幕的自定义控件区域&#xff08;Custom Control&#xff09;实现步骤&#xff1a;需要注意的点是SALV的实例对象和dispaly方法一定是在屏幕PBO事件…

CrossOver 24下载-CrossOver 24 for Mac下载 v24.0.0中文永久版

CrossOver 24是一款可以让mac用户能够自由运行和游戏windows游戏软件的虚拟机类应用&#xff0c;虽然能够虚拟windows但是却并不是一款虚拟机&#xff0c;也不需要重启系统或者启动虚拟机&#xff0c;类似于一种能够让mac系统直接运行windows软件的插件。它以其出色的跨平台兼容…

Spring Initializer环境问题

1.基于jdk8与本地 环境准备 1)下载jdk8并安装 2&#xff09;下载maven 3.6.3并解压放入D盘maven目录下&#xff0c;去掉外层 设置阿里源 打开settings.xml,在mirrors标签之内增加&#xff0c;注意粘贴后</id>中的/有可能被删掉&#xff0c;要自己补上 <mirror>&l…

前端导出word文件的多种方式、前端导出excel文件

文章目录 纯前借助word模板端导出word文件 &#xff08;推荐&#xff09;使用模板导出 前端通过模板字符串导出word文件前端导出 excel文件&#xff0c;node-xlsx导出文件&#xff0c;行列合并 纯前借助word模板端导出word文件 &#xff08;推荐&#xff09; 先看效果&#xf…

HCIP-VLAN综合实验(VLAN的Access接口、Trunk接口、Hybrid 接口、dot1q封装,DHCP设置)

VLAN&#xff08;Virtual Local Area Network&#xff09;即虚拟局域网&#xff0c;是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。每个VLAN是一个广播域&#xff0c;VLAN内的主机间通信就和在一个LAN内一样&#xff0c;而VLAN间则不能直接互通&#xff0c;这样&#…

2024环境工程、能源系统与化学材料国际会议(ICEEESCM 2024)

2024环境工程、能源系统与化学材料国际会议&#xff08;ICEEESCM 2024) 一、【会议简介】 2024环境工程、能源系统与化学材料国际会议&#xff08;ICEEESCM 2024)将于2024年在西安举行。会议将围绕环境工程、能源系统与化学材料等议题展开讨论&#xff0c;旨在为从事环境工程…

idea使用maven创建springboot项目

按照图片中的流程来&#xff0c;就可以创建springboot项目&#xff0c;我这个主要是想做一个JavaWeb项目 有用的话&#xff0c;点个小赞赞再走呀~

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

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

【Django】执行查询—跨关系查询中的跨多值关联问题

跨多值查询 跨越 ManyToManyField 或反查 ForeignKey &#xff08;例如从 Blog 到 Entry &#xff09;时&#xff0c;对多个属性进行过滤会产生这样的问题&#xff1a;是否要求每个属性都在同一个相关对象中重合。 filter() 先看filter()&#xff0c;通过一个例子看&#xf…

【three.js】搭建本地静态服务器 查询API文档使用

目录 一、为什么要搭建本地静态服务器呢&#xff1f; 二、下载three.js文件包 三、vscode配置live-server插件 一、为什么要搭建本地静态服务器呢&#xff1f; 平时学习Three.js&#xff0c;如果你想预览代码3D效果、查询API文档等&#xff0c;咱们需要提供一个本地静态服务…

基于JAVA的快递投保管理系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 软件2.2 布局2.3 技术框架 三、功能模块3.1 保险类型模块3.2 快递管理模块3.3 保险订单模块 四、系统展示五、核心代码5.1 查询快递5.2 查询快递保险5.3 新增快递保险5.4 快递投保5.5 查询保险订单 六、免责说明 一、摘…

LVGL常用部件使用总结之图片部件

图片部件可用于显示图片&#xff0c;图片源可以是 C 语言数组格式的文件、二进制的.bin 文件以及图标字体。值得注意的是&#xff0c;图片部件要显示 BMP、JPEG 等格式的图片&#xff0c;则必须经过解码。 图片部件的组成部分仅有一个&#xff1a;主体&#xff08;LV_PART_MAIN…

硬盘坏了怎么把数据弄出来?数据恢复方法推荐

在数字化时代电脑硬盘中的数据承载着我们的工作成果、生活回忆和珍贵资料。然而一旦硬盘出现故障&#xff0c;数据的安全就变得岌岌可危。那么当电脑硬盘出现问题时&#xff0c;我们真的无法挽回那些重要数据了吗&#xff1f;答案是&#xff1a;不一定&#xff01;本文将为您介…

【Python】【函数】详解Python函数概念

1. 函数定义 函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一&#xff0c;或相关联功能的代码段。 函数能提高应用的模块性&#xff0c;和代码的重复利用率。你已经知道Python提供了许多内建函数&#xff0c;比如print()。但你也可以自己创建函数&#xf…

docker配置数据默认存储路径graph已过时,新版本中是data-root

错误信息 我在修改/etc/docker/daemon.json文件中&#xff0c;添加存储路径graph字段。然后sudo systemctl restart docker包如下错误&#xff1a;使用journalctl -xeu docker.service错误信息&#xff0c;发现不能匹配graph字段。 原因 我的docker版本&#xff1a; 在doc…

RocketMQ安装

这里写目录标题 mq服务端安装配置启动 mq管理界面安装配置启动 mq服务端 安装 RocketMQ下载地址 配置 ROCKETMQ_HOME D:\google-d\rocketmq-all-5.2.0-bin-release启动 # bin目录cmd输入 start mqnamesrv.cmdmq管理界面 安装 下载地址 配置 #修改rocketmq-console\src\…

简单数据类型和复杂数据类型

1. 简单数据类型 null是个特例: 2. 复杂数据类型 3. 堆和栈 注意&#xff1a; JavaScript 中是没有堆和栈的概念的&#xff0c;通过堆栈的概念可以更好的理解代码的一些执行方式&#xff0c;便于将来学习其他语言。 4. 简单数据类型传参 总结&#xff1a;简单数据类型传参传…

吉客云对接打通金蝶云星空销售单查询接口与销售出库新增接口

吉客云对接打通金蝶云星空销售单查询接口与销售出库新增接口 接入系统&#xff1a;吉客云 “吉客云”是一站式企业数字化解决方案系统&#xff0c;可实现业务、财务、办公、人事等一体化管理。相对于传统多套软件系统的集成方案&#xff0c;“吉客云”具有业务流程更流畅&#…

2024年新提出的算法|鹦鹉优化器(Parrot optimizer):算法及其在医疗问题中的应用

本期介绍一种基于训练后鹦鹉关键行为的高效优化方法——鹦鹉优化器(Parrot Optimizer, PO)。该成果于2024年2月发表在中科院2区top SCI期刊Computers in Biology and Medicine&#xff08;IF7.7&#xff09; 1、简介 鹦鹉优化器&#xff08;PO&#xff09;是一种受训练有素的…

政府采购标书制作的要点解析

导语&#xff1a;政府采购是政府为满足公共利益&#xff0c;按照法定程序和标准&#xff0c;通过招标、竞争性谈判等方式&#xff0c;购买商品、工程和服务的行为。标书作为政府采购活动中的重要文件&#xff0c;其制作质量直接影响到项目的顺利进行。本文将围绕政府采购标书制…
最新文章