关于PageHelper何时执行select count(0) from xxx查询?(结论+源码Debug分析)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 关于PageHelper何时执行select count(0) from xxx查询?(结论+源码Debug分析)

关于PageHelper何时执行select count(0)查询?(结论+源码Debug分析)


引子


在使用RUOYI项目中封装在BaseController控制器里这段代码时:


/**
  * 封装成表格对象返回
  * @param list
  * @return
  */
protected TableDataInfo getDataTable(List<?> list){
    TableDataInfo respData = new TableDataInfo();
    respData.setCode(200);
    respData.setMsg("查询成功!");
    respData.setRows(list);
    //这边ruoyi的代码是这样的:respData.setTotal(new PageInfo(list).getTotal());
    //我当时在想不就是取总记录嘛,直接把我select查的集合取其数量不就行了,就改成了这样子的代码
    respData.setTotal(list.size());
    return respData;
}



后来就想到是不是当时自己改分页总记录条数那段代码有问题。果然,我这么取自然总记录数就是我查询列表的记录数嘛,很明显总记录数应该是表的总记录数,接着我就对select count(*) from xxx这个PageHelper自动给我们查询操作进行了源码debug,才比较清楚这个自动执行查询总记录数的执行流程。


结论 +源码debug


先说结论


总结:当我们要使用开启分页查询的时候时,并不是startPage方法中执行的,如下:



真正的执行时机是在对应service中majorMapper执行其代理类的过程中进行的:



在mapper代理类中,会去执行PageHelper拦截器,由于我们之前开启了StartPage(),所以会先去解析我们待查询的sql语句,该sql语句如下所示:


select major_id, major_name
 FROM zf_major
 LIMIT 5;


接着PageHelper会从这条sql中解析其中要查询的表,然后构造出来select count(0) from zf_major这个查询表记录总数的语句,这也是为什么查询总数语句的sql在我们自己编写的select语句之前了的原因(你又没有提前配置它怎么会知道你要分页查哪张表,也在情理之中),最终的查询顺序如下:



PS:其查询得到的记录总数存储在一个PageHelper提供的一个ThreadLocal里,对于我们如何取PageHelper给我们查询的表记录数可以通过如下方式:



源码分析


注:只是截了些较为核心的代码片段,能让自己清楚大致的一个流程,并不是特别特别细


step1:首先确认执行查询总记录的sql是在哪个位置


我们在执行了红框之后的代码可以看到屏幕中就出现了两条sql语句,那么核心代码先进行定位:



step2:进行逐步debug进行排查


这里是走到了PageHelper基于Mybatis的拦截器里




二次定位核心代码,真正执行查询总记录数sql,如下图黄色框代码:



接着重新进行debug打断点进入到该方法中,发现最终是在executeAutoCount方法中执行的:注意可以看到这是PageHelper的拦截器



在这里可以看到代码依据我们要进行select查询的语句进行解析得到了查询该表的sql语句:




其实上面解析出来查询的语句后,后面就是基本的sql执行了,自然就是下面的preparedstatementHandler中



最终执行查询到该表的记录总数:


相关文章
|
SQL Java 数据库连接
Springboot JPA日志输出打印SQL语句和传入的参数 高阶篇
Springboot JPA日志输出打印SQL语句和传入的参数 高阶篇
3325 0
Springboot JPA日志输出打印SQL语句和传入的参数 高阶篇
|
6月前
|
SQL 关系型数据库 MySQL
Greenplum【SQL 02】ROW_NUMBER编号函数使用方法举例
Greenplum【SQL 02】ROW_NUMBER编号函数使用方法举例
156 0
软件测试|深入理解SQL FULL JOIN:语法、用法及示例解析
软件测试|深入理解SQL FULL JOIN:语法、用法及示例解析
|
存储 SQL 安全
Mysql报错注入原理分析(count()、rand()、group by)
Mysql报错注入原理分析(count()、rand()、group by)
239 0
|
SQL 数据库
数据库sql语句(count(*)和count(字段))
数据库sql语句(count(*)和count(字段))
184 0
|
XML SQL Java
如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)
如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)
如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)
|
SQL 关系型数据库 MySQL
SQL练习题--5.6和5.7版本的Group by 用法以及中间表使用
M-统计每个老师教授课程的学生总数-if(expr1,expr2)
365 0
|
存储 关系型数据库 MySQL
MySQL下count(*)、count(1)和count(字段)的查询效率比较
COUNT(*)和COUNT(1)都是对所有结果进行计算。如果有WHERE子句,则是对所有符合筛选条件的数据行进行统计;如果没有WHERE子句,则是对数据表的数据行数进行统计。
435 0
|
关系型数据库 MySQL 数据库
数据库面试题【十九、count(字段) &count(主键 id) &count(1)&count(*)的区别】
数据库面试题【十九、count(字段) &count(主键 id) &count(1)&count(*)的区别】
171 0
下一篇
无影云桌面