PageHelper分页失效,只能查出第一页

PageHelper分页失效,只能查出第一页

  • 1. 现象
  • 2. 原因
  • 3. PageHelper工作原理

1. 现象

  1. 分页代码如下:

    		int pageId = Constants.ONE;
    		boolean isHasNextPage;
    		do {
    			PageHelper.startPage(pageId, Constants.DEFAULT_PAGE_SIZE);
    			List<String> projectIdList = marketingConsStageDAO.getAllProjectId();
    			PageInfo<String> pageInfo = new PageInfo<>(projectIdList);
    			// 此处省略业务逻辑
    			isHasNextPage = pageInfo.isHasNextPage();
    			pageId++;
    		} while (isHasNextPage);
    
  2. marketingConsStageDAO.getAllProjectId()代码如下:

    public List<String> getAllProjectId() {
    
    		Weekend<MarketingConsStage> weekend = Weekend.of(MarketingConsStage.class, true, true);
    		weekend.selectProperties("projectId");
    		weekend.setDistinct(true);
    
    		return marketingConsStageMapper.selectByExample(weekend)
    			.stream()
    			.map(MarketingConsStage::getProjectId)
    			.collect(Collectors.toList());
    	}
    
  3. marketingConsStageDAO.getAllProjectId()应该返回两万余条数据,因此预期do-while循环会执行很多次,但是发现第一页的isHasNextPage就为false,无法继续执行do-while循环;

2. 原因

  1. 进行debug,将断点打到

    PageInfo<String> pageInfo = new PageInfo<>(projectIdList);
    

    这一行,然后发现返回的projectIdListArrayList类型;PageHelper分页失效,只能查出第一页_第1张图片

  2. 看一下PageInfo的构造方法:

    		/**
         * 包装Page对象
         *
         * @param list          page结果
         * @param navigatePages 页码数量
         */
        public PageInfo(List<T> list, int navigatePages) {
            super(list);
            if (list instanceof Page) {
                Page page = (Page) list;
                this.pageNum = page.getPageNum();
                this.pageSize = page.getPageSize();
    
                this.pages = page.getPages();
                this.size = page.size();
                //由于结果是>startRow的,所以实际的需要+1
                if (this.size == 0) {
                    this.startRow = 0;
                    this.endRow = 0;
                } else {
                    this.startRow = page.getStartRow() + 1;
                    //计算实际的endRow(最后一页的时候特殊)
                    this.endRow = this.startRow - 1 + this.size;
                }
            } else if (list instanceof Collection) {
                this.pageNum = 1;
                this.pageSize = list.size();
    
                this.pages = this.pageSize > 0 ? 1 : 0;
                this.size = list.size();
                this.startRow = 0;
                this.endRow = list.size() > 0 ? list.size() - 1 : 0;
            }
            if (list instanceof Collection) {
                calcByNavigatePages(navigatePages);
            }
        }
    
  3. 可以看到,由于projectIdListArrayList类型,因此在创建pageInfo对象时,总页数直接走了this.pages = this.pageSize > 0 ? 1 : 0;的逻辑,导致分页失效;

  4. 如果我们将

    .stream()
    .map(MarketingConsStage::getProjectId)
    .collect(Collectors.toList());
    

    操作放到分页查询操作外面,将代码修改为:

    		int pageId = Constants.ONE;
    		boolean isHasNextPage;
    		do {
    			PageHelper.startPage(pageId, Constants.DEFAULT_PAGE_SIZE);
    			List<MarketingConsStage> marketingConsStageList = marketingConsStageDAO.getAllProjectId();
    			PageInfo<MarketingConsStage> pageInfo = new PageInfo<>(marketingConsStageList);
    			List<String> projectIdList = marketingConsStageList.stream()
    				.map(MarketingConsStage::getProjectId)
    				.collect(Collectors.toList());
          // 此处省略业务逻辑
    			isHasNextPage = pageInfo.isHasNextPage();
    			pageId++;
    		} while (isHasNextPage);
    

    marketingConsStageDAO.getAllProjectId()修改为:

    public List<MarketingConsStage> getAllProjectId() {
    
    		Weekend<MarketingConsStage> weekend = Weekend.of(MarketingConsStage.class, true, true);
    		weekend.selectProperties("projectId");
    		weekend.setDistinct(true);
    
    		return marketingConsStageMapper.selectByExample(weekend);
    	}
    

    然后debug就会发现,marketingConsStageList是一个Page类型变量,此时分页功能就正常了;PageHelper分页失效,只能查出第一页_第2张图片

3. PageHelper工作原理

  1. PageHelper是一个MyBatis分页插件,它可以帮助我们在查询数据的时候进行分页处理。当我们调用PageHelper.startPage(pageNum, pageSize)方法时,它会在底层使用ThreadLocal来保存当前线程的分页参数,然后通过拦截器对SQL语句进行改写,从而实现分页查询。
  2. 在我们调用完PageHelper.startPage(pageNum, pageSize)方法后,紧接着执行的SQL查询语句会被PageHelper拦截并进行改写,从而在查询结果的时候只返回指定页数和每页记录数的数据。PageHelper会将查询结果封装成一个Page对象,这个Page对象包含了查询结果的总记录数、当前页数、每页记录数以及查询结果的数据列表。
  3. 因此,当我们调用查询方法后,返回的list可以被PageHelper包装成Page对象。这是因为PageHelper在底层对查询结果进行了封装,将查询结果以Page对象的形式返回给了调用方。调用方可以通过Page对象获取查询结果的各种信息,如总记录数、当前页数、每页记录数等,同时也可以通过Page对象获取查询结果的数据列表。
  4. 总之,通过PageHelper实现分页查询的过程可以概括为:开启分页查询 -> 执行查询操作 -> 将查询结果列表返回给调用方,并以Page对象的形式包装 -> 调用方通过Page对象获取分页查询的各种信息。

你可能感兴趣的:(java,mybatis)