java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > PageHelper分页失效解决

PageHelper中分页失效的原因分析与正确方法实践

作者:秧歌star519

在使用 PageHelper 插件开发查询接口时,有时会出现分页失效的情况,下面小编就和大家详细讲讲分页失效的原因分析与正确方法,希望对大家有所帮助

1. 问题现象

在使用 PageHelper 插件开发查询接口时,出现分页失效的情况:接口返回了全部数据而非当前页数据,且 PageInfo 对象中的分页元数据(如 total 总条数、pages 总页数)计算错误。

错误代码示例

public BaseResponse<MyDataDTO> queryDataList(int pageNum, int pageSize, Map<String, Object> params) {
    BaseResponse response = new BaseResponse();
    
    // 1. 错误:在设置分页参数前执行了数据库查询
    List<MyDataDTO> dataList = myMapper.selectData(params);
    
    // 2. 判空逻辑
    if (!CollectionUtils.isEmpty(dataList)) {
        // 3. 错误:查询早已完成,此时调用 startPage 无效
        PageHelper.startPage(pageNum, pageSize);
        
        // 4. 错误:直接使用全量 List 包装 PageInfo,无法获取数据库真实总数
        PageInfo<MyDataDTO> pageInfo = new PageInfo<>(dataList);
        
        response.setResult(wrapPageResult(pageInfo));
        return response;
    }
    
    response.setResult(Collections.EMPTY_LIST);
    return response;
}

2. 原理分析

PageHelper 的核心机制基于 ThreadLocalMyBatis 拦截器(Interceptor)

2.1 执行流程

PageHelper 不是在内存中对结果集进行截取,而是通过拦截器修改 SQL 语句。

设置参数:调用 PageHelper.startPage(...) 时,插件会将分页参数(pageNum, pageSize)存入当前线程的 ThreadLocal 中。

拦截 SQL:当 MyBatis 执行 Mapper 方法时,PageHelper 拦截器会触发。

SQL 改写

清理上下文:SQL 执行结束后,拦截器会清除 ThreadLocal 中的分页参数,避免污染后续查询。

2.2 失效原因

在上述错误代码中:

3. 正确实现

核心原则PageHelper.startPage 必须紧邻 Mapper 查询方法之前调用。

修正代码

public BaseResponse<MyDataDTO> queryDataList(int pageNum, int pageSize, Map<String, Object> params) {
    BaseResponse response = new BaseResponse();

    // 1. 设置分页参数(存入 ThreadLocal)
    PageHelper.startPage(pageNum, pageSize);
    
    // 2. 执行查询(拦截器生效,自动改写 SQL 并执行 Count 查询)
    // 注意:此时返回的 list 实际类型为 Page<E>
    List<MyDataDTO> dataList = myMapper.selectData(params);

    // 3. 获取分页结果
    PageInfo<MyDataDTO> pageInfo = new PageInfo<>(dataList);
    
    // 4. 结果处理(PageInfo 可安全处理空集合)
    if (!CollectionUtils.isEmpty(dataList)) {
         // pageInfo.getTotal() 为数据库真实总数
         response.setResult(wrapPageResult(pageInfo));
    } else {
         response.setResult(Collections.EMPTY_LIST);
    }
    
    return response;
}

4. 最佳实践与注意事项

严格遵守调用顺序 必须保证 startPage -> Mapper查询 -> PageInfo包装 的执行顺序。

避免逻辑穿插 严禁在 startPageMapper查询 之间插入其他 SQL 操作或复杂逻辑。

风险:PageHelper 的分页参数是“一次性消费”的。如果在分页查询前插入了其他 SQL(如查询用户信息),分页参数会被那条 SQL 消费掉,导致原本需要分页的主查询失效。

PageInfo 的健壮性 无需为了判空调整代码顺序。PageInfo 对空 List 有良好的兼容性,若查询结果为空,它会自动设置 total=0,不会抛出异常。

大数据量风险 如果因顺序错误导致分页失效,全量查询可能会将百万级数据加载至内存,极易引发 OOM(内存溢出),影响系统稳定性。

到此这篇关于PageHelper中分页失效的原因分析与正确方法实践的文章就介绍到这了,更多相关PageHelper分页失效解决内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文