PageHelper.startPage(param.getPageNum(), param.getPageSize());
List<PjResult> results = pjglMapper.selectPjResult(param); // 第一次查询
param.setPjResults(results);
List<PjSYQK> usedList = pjglMapper.selectPjSyqk(param); // 第二次查询
如何只让第一次的查询分页,第二次的查询不分页呢?目前的问题是两次查询全部被分页了。如何解决这一问题呢?
PageHelper.clearPage()已经尝试过,无法去除分页问题。
第一次调用结束后执行PageMethod.clearPage(); 再试试。
1、网上有资料 https://blog.csdn.net/chen1992xin/article/details/103893448
解决方案:
(一)在执行这个不分页的查询之前,先把分页的参数拿到:
Page page = PageHelper.getLocalPage();
(二)然后把当前线程中的PageHelper本地变量移除:
PageMethod.clearPage();
2、换个思路,单独查分页的封装一下,可好?
不分页方法:
PageHelper.startPage(0, 0,false,null,true);
我的问题解决了,,和大家分享下解决过程:
1、分析问题
PageHelper.startPage之后,官方文档给的解释是:
所以正常情况下,PageHelper.startPage之后第一次mapper查询会进行分页操作。
分页的原理大概是(粗略描述):
1.PageHelper在ThreadLocal里存放分页的一些参数,通过拦截器拦截mybatis的查询操作
2.sql拼接成分页的效果(mysql通过limit,oracle通过rownum)
3.执行查询
4.对ThreadLocal的参数进行重置,对代理进行remove。
通过这样的操作,执行一次查询就将分页参数给消费掉,才会实现PageHelper.startPage后面紧跟的第一个查询操作才会被分页。但是我遇到的问题是,第二次查询操作也被分页了!说明问题不在于PageHelper.startPage的问题。
2、调试测试
PageHelper的每次查询操作后,都会对参数和代理器进行重置,会不会是由于某些特定原因导致PageHelper没有进行重置操作呢?于是我自己进行了手动重置:
PageHelper.startPage(param.getPageNum(), param.getPageSize());
List<PjResult> results = pjglMapper.selectPjResult(param); // 第一次查询
param.setPjResults(results);
PageHelper.clearPage();
List<PjSYQK> usedList = pjglMapper.selectPjSyqk(param); // 第二次查询
写完之后发现第二次查询还是被分页了。并且debug跟进,发现两个查询都是走了完整的分页流程。说明PageHelper.startPage()已经不是我开启分页的直接原因了。好像不写startPage依然可以分页!
那么我把PageHelper.startPage去掉,执行结果会如何呢?
List<PjResult> results = pjglMapper.selectPjResult(param); // 第一次查询
param.setPjResults(results);
List<PjSYQK> usedList = pjglMapper.selectPjSyqk(param); // 第二次查询
结果发现真的全部都分页了。而且两个查询用的都是同一种类型的参数param。
看一下param是否有问题:
public class PjParam extends BaseQuery {
public class BaseQuery extends PageInfoEntity {
看到这里,PageHelper.startPage(param.getPageNum(), param.getPageSize());这句代码,分页的参数也是从param里拿的,而且分页的属性正是PageInfoEntity的属性。所以尝试到这里,只有一个原因了。那就是引入PageInfoEntity的jar包也在某个地方引入了拦截器,对于PageInfoEntity这个实体类,只要分页参数有值,就会自动进行分页。也解释了为什么不写startPage也依然可以分页。
3、解决方法
既然是因为拦截器的原因,那么可以将PageInfoEntity的分页参数置空,让拦截器不生效。
也可以用PageHelper的方法:
PageHelper.startPage(param.getPageNum(), param.getPageSize());
List<PjResult> results = pjglMapper.selectPjResult(param);
param.setPjResults(results);
PageHelper.startPage(0, 0,false,null,true); // 调用PageInfo的方法
List<PjSYQK> usedList = pjglMapper.selectPjSyqk(param);
对于PageHelper.startPage这个方法,重载了很多次,其中一个startPage源码是这样写的:
/**
* 开始分页
*
* @param pageNum 页码
* @param pageSize 每页显示数量
* @param count 是否进行count查询
* @param reasonable 分页合理化,null时用默认配置
* @param pageSizeZero true且pageSize=0时返回全部结果,false时分页,null时用默认配置
*/
public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
Page<E> page = new Page<E>(pageNum, pageSize, count);
page.setReasonable(reasonable);
page.setPageSizeZero(pageSizeZero);
//当已经执行过orderBy的时候
Page<E> oldPage = getLocalPage();
if (oldPage != null && oldPage.isOrderByOnly()) {
page.setOrderBy(oldPage.getOrderBy());
}
setLocalPage(page);
return page;
}
解铃还须系铃人
PageHelper.startPage(trainPlatformParamsVo.getPageNum(), trainPlatformParamsVo.getPageSize());
List<ReceivblesVerification> verificationList = receivblesVerificationMapperDetail.findInvoiceInfo(trainPlatformParamsVo);
ReturnPageData<ReceivblesVerification> returnPageData = new ReturnPageData<>(verificationList);
returnPageData.getList().forEach(verification -> {
TrainPlatformParamsVo platformParamsVo = new TrainPlatformParamsVo();
platformParamsVo.setTrxNum(verification.getTrxNum());
PageHelper.startPage(0, 0,false,null,true);
List<Receivables> receivables = receivblesVerificationMapperDetail.findReceivablesByTrxNum(platformParamsVo);
verification.setVerificationTotalAmt(receivables.stream().map(Receivables::getVerificationAmt).reduce(BigDecimal.ZERO, BigDecimal::add));
verification.setReceivablesList(receivables);
})
分页的前提是需要传入参数的,你可以通过传递参数进行控制,第一次传递分页的参数,第二次查询不传递参数,然后通过判断有无参数进行调用分页插件PageHelper.startPage(param.getPageNum(), param.getPageSize());
不知道你这代码怎么写的,mybatis有一级缓存,如果是自己手动获取mapper或者加了事务,才会出现这种情况(本质是sqlsession复用),这种解决也好处理