当前位置:   article > 正文

PageHelper插件的认识_pagehelp手写count

pagehelp手写count

一  前言

对于pageHelper 插件的使用呢,一直稀里糊涂,结果是分页能不能成功全靠运气。于是自己大致跟了下代码,虽然好多也没看懂,仅当自己的学习笔记啦。如果能帮到网友,就同乐了呀!

二 使用

  1. @Override
  2. public PageInfo<ReportInfo> physicalreportlist(ReportReqVo reportReqVo, Integer pageNum, Integer pageSize) {
  3. PageHelper.startPage(pageNum, pageSize);
  4. List<ReportInfo> req = reportMapper.findByCondition(reportReqVo);
  5. PageInfo<ReportInfo> page = new PageInfo<>(req);
  6. List<ReportInfo> result = new ArrayList<>();
  7. if (CollectionUtils.isNotEmpty(req)) {
  8. result= reportMapper.selectphysicalreportlist(req);
  9. }
  10. page.setList(result);
  11. return page;
  12. }

      说明:对于单条sql查询,只要把查询语句紧挨着写在PageHelper.startPage(pageNum, pageSize)下面。如果一条sql查询不能搞定,也是将第一次查询的sql紧挨着写在pageHelper.startPage(pageNum, pageSize)下面。多次查询,肯定有个初始数据源。像我这里,req就是初始数据,查出所有id,供第二次查询用。

      注意:PageHelper.startpage()执行后就开始分页,第一行sql每次都执行pageSize。按道理讲,第二次查询和第一次查询的

条数应该是一样的,不然,你分页信息是每页10条,但是实际情况少于10条。所以这里要注意两点:

              1 第二次最好根据id查询

              2 left join也可能影响第二次查询结果的条数。

      这里可以做个试验。将这里第二查询语句,假如只取前5条,你会在页面看到这样的信息:分页信息都是对的,只是每页分页的数据只有5条!

      建议:最好按照下面的步骤写!

              1 

  1. PageHelper.startPage(pageNum, pageSize);
  2. List<ReportInfo> req = reportMapper.findByCondition(reportReqVo);
  3. PageInfo<ReportInfo> page = new PageInfo<>(req);

              2 做二次处理(可能不需要)

              3 return page

三 原理简单分析

       第一行:PageHelpler.startPage(pageNum, pageSize) 就会把分页初始信息准备好,还有个默认参数count(默认值true),查询出total(总条数)。

        截取部分代码:注意这里的setLocalPage()

  1. Page<E> page = new Page<E>(pageNum, pageSize, count);
  2. page.setReasonable(reasonable);
  3. page.setPageSizeZero(pageSizeZero);
  4. //当已经执行过orderBy的时候
  5. Page<E> oldPage = getLocalPage();
  6. if (oldPage != null && oldPage.isOrderByOnly()) {
  7. page.setOrderBy(oldPage.getOrderBy());
  8. }
  9. setLocalPage(page);
  10. return page;

 

       第二行:执行了第一行代码后,他已经控制了第二条查询语句每次查询的条数。原来,在执行sql前,插件使用使用了拦截器,保证这条sql每次只执行pageSize条。具体实现不是很清楚。而且每次都会查询出count

 

       截取部分代码:

       

  1. public Object intercept(Invocation invocation) throws Throwable {
  2. try {
  3. Object[] args = invocation.getArgs();
  4. MappedStatement ms = (MappedStatement) args[0];
  5. Object parameter = args[1];
  6. RowBounds rowBounds = (RowBounds) args[2];
  7. ResultHandler resultHandler = (ResultHandler) args[3];
  8. Executor executor = (Executor) invocation.getTarget();
  9. CacheKey cacheKey;
  10. BoundSql boundSql;
  11. //由于逻辑关系,只会进入一次
  12. if(args.length == 4){
  13. //4 个参数时
  14. boundSql = ms.getBoundSql(parameter);
  15. cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
  16. } else {
  17. //6 个参数时
  18. cacheKey = (CacheKey) args[4];
  19. boundSql = (BoundSql) args[5];
  20. }
  21. List resultList;
  22. //调用方法判断是否需要进行分页,如果不需要,直接返回结果
  23. if (!dialect.skip(ms, parameter, rowBounds)) {
  24. //反射获取动态参数
  25. String msId = ms.getId();
  26. Configuration configuration = ms.getConfiguration();
  27. Map<String, Object> additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
  28. //判断是否需要进行 count 查询
  29. if (dialect.beforeCount(ms, parameter, rowBounds)) {
  30. String countMsId = msId + countSuffix;
  31. Long count;
  32. //先判断是否存在手写的 count 查询
  33. MappedStatement countMs = getExistedMappedStatement(configuration, countMsId);
  34. if(countMs != null){
  35. count = executeManualCount(executor, countMs, parameter, boundSql, resultHandler);
  36. } else {
  37. countMs = msCountMap.get(countMsId);
  38. //自动创建
  39. if (countMs == null) {
  40. //根据当前的 ms 创建一个返回值为 Long 类型的 ms
  41. countMs = MSUtils.newCountMappedStatement(ms, countMsId);
  42. msCountMap.put(countMsId, countMs);
  43. }
  44. count = executeAutoCount(executor, countMs, parameter, boundSql, rowBounds, resultHandler);
  45. }
  46. //处理查询总数
  47. //返回 true 时继续分页查询,false 时直接返回
  48. if (!dialect.afterCount(count, parameter, rowBounds)) {
  49. //当查询总数为 0 时,直接返回空的结果
  50. return dialect.afterPage(new ArrayList(), parameter, rowBounds);
  51. }
  52. }

 

 

 

       第三行:截取了部分代码:

  1. if (list instanceof Page) {
  2. Page page = (Page) list;
  3. this.pageNum = page.getPageNum();
  4. this.pageSize = page.getPageSize();
  5. this.pages = page.getPages();
  6. this.list = page;
  7. this.size = page.size();
  8. this.total = page.getTotal();
  9. //由于结果是>startRow的,所以实际的需要+1
  10. if (this.size == 0) {
  11. this.startRow = 0;
  12. this.endRow = 0;
  13. } else {
  14. this.startRow = page.getStartRow() + 1;
  15. //计算实际的endRow(最后一页的时候特殊)
  16. this.endRow = this.startRow - 1 + this.size;
  17. }
  18. ....
  19. ....
  20. }

       这一句主要目的,我认为就是获取整个分页信息!

       这里只是冰山一角,有好多没看懂,list强制转成page对象后,debug中根据获取不到pages total信息,是我太菜了呀!

      

四 补充

       先这样吧,以后再补充,不过一定要按照我上面的步骤写分页。有不对的,请指明!

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/676994
推荐阅读
相关标签
  

闽ICP备14008679号