mybatis源码(五)springboot pagehelper实现查询分页

29 篇文章 10 订阅
订阅专栏
本文详细解释了SpringBoot中PageHelper插件的加载时机、生效机制,以及分页逻辑的实现过程,涉及mybatis代理、ThreadLocal、分页拦截器和jsqlparser工具。
摘要由CSDN通过智能技术生成

1、背景

springboot的pagehelper插件能够实现对mybatis查询的分页管理,而且在使用时只需要提前声明即可,不需要修改已有的查询语句。使用如下:

之前对这个功能一直很感兴趣,但是一直没完整看过,今天准备详细梳理下。按照个人的习惯,我喜欢带着问题去看源码,这次浏览源码我希望可以了解以下两个问题:
1)分页插件什么时候被加载的
2)分页插件什么时候生效的,如何生效的

2、技巧(可跳过)

mybatis自身的功能原理这里我们不深入探讨,网上文章很多,我之前也写过类似的文章,这里为了防止文章杂乱,我们只关注感兴趣的点,即mybatis pagehelper分页原理,其它的一笔带过。另外因为mybatis查询生效都是用的代理对象。如果对源码不是很熟悉,很难第一时间找到打断点的位置。不过通过查看page的源码可以知道,最后的分页参数都放到了threadlocal对象里,如下:




而最后使用该threadlocal时是一定会调用它的获取和移除方法,因此我们在它的这两个方法中加断点。等进入断点后再通过方法栈追踪其全流程。如下:

3、源码追踪流程

有了上述方法栈的查看,我们知道了查询的入口和大体流程,现在重新执行查询跟随源码脚步来详细看下分页的实现逻辑。首先是在代码中我们主动进行分页查询,如下:

前三行代码很简单,主要是从httpservletrequest中获取分页参数,并设置到当前线程的threadlocal变量中。第四行则是调用接口方法进行查询。在mybatis中,接口方法最终功能的实现主要是依靠MapperProxy代理类实现(代理类中包含接口和xml配置相关信息),所以接下来我们直接到MapperProxy中打断点追踪(至于mybatis如何关联接口和mapper.xml文件,MapperProxy如何生成等问题不是本文讨论重点,感兴趣的可以单独去查阅或者浏览我以前的相关文章)。

MapperProxy是代理对象,主要调用方法是invoke方法,所以在该方法中加断点,或者依靠第二步中的技巧查看整个查询的方法栈,随后再在MapperProxy对应的行中加断点。具体断点信息如下:

因为method不是Object类型,所以执行else里面的代码:

可以看到最后会执行PlainMethodInvoker对象里的invoke方法,所以我们接着到该方法中打断点并继续追踪查看:

可以看到调用SqlSessionTemplate对象的selectList方法,我们接着向下看:

再接着到DefaultSqlSession中继续查看:

可以看到,最后会调用CachingExecutor的query方法,但是这里要留意一点,那就是CachingExecutor是一个代理对象,执行代理对象方法首先要进入代理,并执行invoke方法。我们这里通过断点调试的步入查看执行哪个类的invoke方法:

可以看到最终是通过Plugin代理实现CachingExecutor对象query方法的调用。我们再接着向下看:

因为要执行的方法是查询方法,其是分页拦截器指定要拦截的方法类型,所以会进入拦截方法中。这里我标记了两个框,第一个是拦截,第二个是不进行拦截直接执行查询方法,因此可以推测分页逻辑是再拦截器中进行的。拦截器中会进行sql的改写,所以这里进入拦截器中进一步查看。拦截器对象为PageInterceptor到这终于和本文的主题关联上了,接下来我们到分页拦截器中看一下:

可以看到源码中都加好注释了,看起来就更简单了,这里我们看下进入分页的条件:

可以看到最后获取的page对象实际上就是我们一开在代码中传入分页参数创建的page对象。因为page对象不为空,所以会返回false,进而不跳过分页逻辑。(另外这里要提醒下各位小伙伴,page对象继承了ArrayList,所以断点查看时看不得page里面的内容,只能看到其size为0。)

我们接着回到主流程向下看,随后会判断是否需要计算总数,默认创建page时需要计算总数,这里我们就不进入before方法查看了,里面逻辑比较简单。下面我们简单看下计算总数的逻辑:

可以看到其计算总数的sql比较精简,主要是根据查询的对象和条件直接计算总数。这里sql的解析和生成主要是依赖jsqlparser工具类实现(jsqlparser的使用可以参考我以前的文章),sql解析比较复杂,感兴趣的可以自行查看。接着我们再回到主流程,看下何时添加的分页查询参数:

可以看到最后再sql末尾加了limit分页参数,而这个sql的改写过程与计算count类似,都是通过jsqlparser工具实现的。

通过上面的流程,我们已经知道了分页插件如何生效的了。但是还有一个问题是分页插件如何被加载的。这个流程比较简单,我也是通过第二步的技巧逆推的全流程。下面我按照正常项目的加载顺利简单介绍下:
当我们在pom中引入pageHelper插件依赖并且在yml中配置分页相关的信息时,项目启动后就会主动的进行插件的初始化并注入到插件拦截器链里面。大体逻辑如下:

可以看到分页插件有个配置类,其在项目初始化的时候会创建分页拦截器,并调用Configuration进行添加,接着我们看下最后会将拦截器添加到哪里:

可以看到最终会添加到拦截器链对象的私有集合里。但是我们最终使用拦截器是在Plugin对象里用的,而不是在拦截器链里面,那Plugin如何使用到该拦截器的呢?

拦截器链里有个pluginAll方法,它会封装拦截器成一个“链式”动态代理对象,代理类是Plugin,该方法会在创建Executor时执行(还记得前面源码里介绍这块的提醒吧,Executor是一个被动态代理的对象),通过pluginAll方法,将拦截器封装成链并将Executor放在链路最后一层

可以看到通过pluginAll方法将拦截器封装成了一个链,下面再看一下Executor的创建就完全清晰了:

至此,我们两个问题都再浏览源码的过程中清晰了。

4、总结

1)该文章主要是探究sringboot分页插件实现的原理,所以对于mapper.xml与接口方法的整合和mybatis代理对象如何实现查看没有细讲,但是这部分也是查询过程中核心的代码。

2)由PageInterceptor分页拦截器拦截指定的查询请求,然后在拦截方法中调用PageHelper中的方法对sql进行改写,最后再进行提交。

2)无论计算总数还是重写分页sql,都是通过jsqlparser工具实现的(为了使得文章主题清晰,这里没有介绍sql的改写过程,jsqlparser的使用可以浏览我以前的文章)

3)Plugin是一个链式动态代理对象,最后一个节点是Executor被代理对象,前面的节点是Interceptor被代理对象。

4)再Plugin.wrap方法中会提取出拦截器里的signature标签,并保存在每个Plugin链式代理对象中。在被代理对象执行对应方法时,如果plugin代理对象包含对应的signature集合则说明当前被代理对象是拦截器,如果不包含signature或者signature标签没有拦截当前方法,则直接执行当前方法。

参考文章:

5分钟!彻底搞懂MyBatis插件+PageHelper原理 - 知乎

Spring Boot分页查询
衍生星球的博客
09-06 800
分页查询是日常开发中比较常用的功能。MyBatis框架下也有很多插件实现分页功能,比如pageHelper。这是一款非常简单、易用的分页插件,能很好地集成在Spring Boot中。pageHelper是一款基于MyBatis的数据库分页插件,所以我们在使用它时需要使用MyBatis作为持久层框架。
7.3 SpringBoot整合MyBatis分页插件github.pageHelper实现图书列表API
天罡gg的专栏
07-02 4772
在软件开发中,分页是一个非常常见的需求,无论是在Web应用程序还是在移动应用程序中,我们经常需要将大量的数据分成多个页面进行展示。本文主要实现图书列表API,使用SpringBoot集成MyBatis分页插件github.pageHelper,首先会从「自己实现分页原理」说起,再到「使用github.pageHelper实现分页以及注意点」,最后回到图书借阅系统实战项目中,「结合通用分页结果」,实现「统一规范的图书列表API」,读完本文,你就可以轻松拿捏通用分页
SpringBoot实现分页查询
CoCo629vanilla的博客
03-29 1万+
前言
PageHelper组件 实现前端分页查询功能
最新发布
小谷同学的博客
09-07 1136
后端使用PageHelper组件+前端使用ElementUI实现分页,解析+源码,内容十分详细。
Spring-Boot MyBatis Pagehelper分页查询
wildkid
03-02 228
Spring-Boot MyBatis Pagehelper分页查询
Mybatis】使用PageHelper进行分页查询
Flying_Ape的博客
11-29 3571
而且这个插件的优点是分页与mapper.xml完全解耦,有效的避免了直接写分页sql来实现分页功能。2、一定要在查询之前引入,它会自动对该代码下的第一个查询进行分页,即: findByCountryProjectName。分页插件的基本原理是使用mybatis提供的 插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后。1、使用pagehelper进行分页查询时,,无需写分页语句,对于其他的查询条件可正常编写。1、dao层代码入参中只需写查询条件,无需写分页入参。
MyBatis之使用pageHelper插件进行分页查询
itigoitie的博客
06-28 979
MyBatis之使用PageHelper插件进行分页查询
SpringBoot实现MyBatis分页
zih78888888的博客
05-18 164
综合概述 想必大家都有过这样的体验,在使用Mybatis时,最头痛的就是写分页了,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 select,幸好我们有 pagehelper 分页插件,pagehelper 是一个强大实用的 MyBatis 分页插件,可以帮助我们快速的实现MyBatis分页功能,而且pagehelper有个优点是,分页和Mapper.xml完全解耦,并以插件的形式实现,对Mybatis执行的流
SpringBoot+Mybatis实现分页查询
热门推荐
独钓寒江雪
06-26 2万+
文章目录前言1.引入依赖2.Mapper中接口3.修改XML文件4.controller层调用接口5.测试总结 前言 分页查询是在web开发中常用的一种技术,当某个页面查询返回的数据量较大时,为了提高性能和用户体验不能将所有数据一次性返回给过前端,这时候就需要用到分页查询PageHelper是一款开源的Mybatis第三方物理分页插件,spring boot项目中集成PageHelper插件非...
Spring Boot实现MyBatis分页
javalingyu的博客
04-29 4230
综合概述 想必大家都有过这样的体验,在使用Mybatis时,最头痛的就是写分页了,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 select,幸好我们有 pagehelper 分页插件,pagehelper 是一个强大实用的 MyBatis 分页插件,可以帮助我们快速的实现MyBatis分页功能,而且pagehelper有个优点是,分页和Mapper.xml完全解耦,并以插件的形式实现,对Mybatis执行的
SpringBoot使用PageHelper分页查询
XiaoLuZaiZi的博客
12-23 154
pagehelper使用
Mybatis使用pageHelper实现分页查询
睡不醒大猫的博客
04-22 581
原文链接:https://blog.csdn.net/qq_35387940/article/details/91530234。UserServiceImpl实现层。UserController层。IUserService层。
mybatis 插件pagehelper实现分页查询
振峰的博客
09-25 164
https://www.cnblogs.com/xifengxiaoma/p/11027551.html
Springboot使用pageHelper实现分页查询
Aplumage的专栏
07-26 552
Springboot使用pageHelper实现分页查询 第一步: pom.xml添加依赖: <!--分页插件 pagehelper --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <!-- 特别注意版本问题 --> ...
Spring Boot中使用PageHelper实现分页查询
qq_42800468的博客
07-06 1346
本文将介绍如何在Spring Boot项目中使用PageHelper插件进行分页查询
MyBatis使用PageHelper插件实现分页查询
qq_63524487的博客
07-01 480
/</</</
Java Web Spring Boot 分页查询插件-PageHelper
xycxycooo的博客
07-24 395
PageHelperMyBatis的一款功能强大、方便易用的分页插件,支持任何形式的单表、多表的分页查询。它能够自动拦截SQL查询,并在查询前添加分页参数,查询后返回分页结果。@Mapper@Service@Autowired@Override// 设置分页参数// 执行分页查询// 获取分页结果// 封装PageBean@Autowired。
SpringBoot】-- 使用PageHelper实现分页查询
张修宇的博客
04-26 657
调用PageHelper的startPage方法;根据条件查询数据库中所有的数据并保存到list中,将list强转为Page类型,调用Page类型的setTotal和setItems方法可以实现分页,最后返回PageBean。前端需要传入页码和每页数量。以PageBean类型返回。
写文章

热门文章

  • mysql通过binlog恢复或回滚数据 30236
  • Sql解析转换之JSqlParse完整介绍 21536
  • vue技巧(九)跨域及跨域配置不生效原因探究 12637
  • clickhouse报错 Connection refused: connect 12151
  • windows10的etc路径下没有hosts文件 7553

分类专栏

  • 源码系列 29篇
  • 前端知识 — 基础 + vue + react 14篇
  • 基础知识 25篇
  • 笔记感悟 4篇
  • 大数据 24篇
  • 数据库 6篇
  • 错误记录 12篇

最新评论

  • binlog2sql 工具安装使用及问题汇总

    hfx_2021: 厉害啊。和我遇到的问题一模一样。全都解决了

  • 双时钟系统服务(java)

    CSDN-Ada助手: 不知道 Java 技能树是否可以帮到你:https://edu.csdn.net/skill/java?utm_source=AI_act_java

  • hue(一)编译、启动、使用

    Interest1_wyt: 你好,没有遇到过你的问题,所以不能给予你建议。另外编译时间我当时很快,应该没有超过10分钟,这40分钟感觉不正常。

  • hue(一)编译、启动、使用

    weixin_46431229: 博主你好!我在编译hue4.11遇到下面的问题: ModuleNotFoundError: No module named 'daemon' 不知你遇到过吗? 我一路以来的过程是这样的: 1、docker 启动 连接hive, impala 解决了一路问题,通过 2、想对Hue作一些改造,遂搭建开发环境: 2.1 源码编译,环境是:window wsl ubuntu22 python3.8 解决了几个“No module”问题后,就遇到上面这个问题,死活过不去,于是找到你的文章,目前正在make clean过程中 2.2,使用pycharm搭建开发环境(未完成,查到需要用于编译后的build/env目录才有的2.1步骤) 另外,我现在编译一次要40分钟左右,太慢了,正常吗?一天搞不了几次,悉。。。 感谢感谢!!!!表情包

  • windows10的etc路径下没有hosts文件

    Interest1_wyt: dir不是文件,是路径参数,你看看是不是dir前面的标点符号整错了

最新文章

  • 每类数据保留前n条(sql)
  • spring security源码追踪理解(二)
  • spring security源码追踪理解(一)
2024年6篇
2023年22篇
2022年30篇
2021年54篇
2020年10篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

深圳坪山网站建设公司网站的优化采选火30星棒北京市网站优化厂商网站优化加盟企业余杭区网站排名优化服务吴川网站建设及优化武汉网站排名优化做优化需要网站源代码吗新乡百度网站推广优化网站优化到第一页济南口碑好的机械行业网站优化锡林郭勒盟网站排名优化宜城网站内部优化富阳网站优化公司徐州睢宁网站优化公司望江网站优化多少钱移动网站优化是什么意思品牌网站结构优化青浦区公司网站优化平台滦县服务好的网站优化滑县网站优化公司有口碑的网站优化推广景德镇网站优化枝江关键词网站优化黄冈低成本网站优化公司排名怎样做网站seo优化长沙品质营销型网站优化建筑网站优化规划均安网站优化入门焦作网站优化价格华容区网站做优化多少钱香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

深圳坪山网站建设公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化