在Java开发中,MyBatis Plus和PageHelper都是非常流行的MyBatis扩展插件,它们分别提供了便捷的查询封装和分页功能。许多开发者在项目中同时使用这两个插件时,常会遇到分页信息不准确的问题。本文将从常见问题现象出发,分析原因,并提供有效的解决方案,以帮助大家在开发中更好地使用这两个插件。
问题现象
在项目中,我们期望通过PageHelper来分页查询数据,并配合MyBatis Plus的LambdaQueryWrapper
进行条件查询。例如:
int pageNum = 2; int pageSize = 2; // 配置分页参数 PageHelper.startPage(pageNum, pageSize); // 使用 MyBatis Plus 的查询封装 LambdaQueryWrapper<DataPerson> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(DataPerson::getDelFlag, DelFlagEnum.NORMAL.getCode()); // 使用 selectVoList 查询 List<DataPersonVO> oldPersons = mapper.selectVoList(wrapper); PageInfo<DataPersonVO> pageInfo = new PageInfo<>(oldPersons); System.out.println(pageInfo);
按预期,pageInfo
中应该显示正确的分页信息,但实际输出显示 pageNum
一直是 1
,isLastPage
总是 true
,分页不生效。进一步分析SQL发现,selectVoList
方法在数据库查询时确实被正确加上了LIMIT
分页参数,因此数据集是正确的,但分页对象 PageInfo
的 pageNum
等属性却不正确。
原因分析
PageHelper在MyBatis拦截层添加分页参数,以自动修改生成的SQL。但它的分页上下文信息捕获依赖于标准MyBatis查询,而MyBatis Plus的selectVoList
等扩展方法生成SQL的方式有所不同,导致PageHelper在生成PageInfo
时没有正确捕获pageNum
等分页上下文。
具体原因包括:
PageHelper的分页拦截机制:PageHelper依赖于MyBatis生成的SQL查询,以自动在SQL中添加分页参数并生成分页对象,但某些MyBatis Plus特有方法如
selectVoList
不一定符合这种机制,可能会导致分页参数未被正确传递。PageHelper和MyBatis Plus方法的兼容性问题:尽管PageHelper能在查询中加入分页参数,但对于MyBatis Plus的扩展方法(如
selectVoList
),分页上下文可能未正确传递到PageInfo
中,导致页面数据不一致。
解决方案
针对以上问题,我们可以考虑以下几种解决方案:
方案一:使用MyBatis Plus自带的分页插件
MyBatis Plus自带了分页插件,完全支持MyBatis Plus扩展方法如selectVoList
,适配性更高,可以确保分页查询和分页信息的一致性。具体步骤如下:
确保项目中已配置了MyBatis Plus的分页插件,例如在Spring Boot项目中引入
PaginationInterceptor
。使用MyBatis Plus的
Page
对象来进行分页查询:import com.baomidou.mybatisplus.extension.plugins.pagination.Page; int pageNum = 2; int pageSize = 2; // 使用 MyBatis Plus 的分页对象 Page<DataPersonVO> page = new Page<>(pageNum, pageSize); // 执行分页查询 page = mapper.selectVoList(page, wrapper); // 获取分页信息 long total = page.getTotal(); // 总记录数 long totalPages = page.getPages(); // 总页数 List<DataPersonVO> data = page.getRecords(); // 当前页数据
使用MyBatis Plus的分页插件可以确保分页数据准确,包括pageNum
、isLastPage
等分页信息正确显示。
方案二:自定义Mapper方法
如果由于项目限制,无法更换为MyBatis Plus分页插件,可以选择在Mapper中自定义方法,通过编写SQL语句,避免MyBatis Plus的扩展方法干扰PageHelper
的分页效果。
在
Mapper
接口中定义自定义查询方法:List<DataPersonVO> customSelectVoList(@Param("wrapper") Wrapper<DataPerson> wrapper);
在XML中编写SQL语句:
<select id="customSelectVoList" resultType="DataPersonVO"> SELECT * FROM data_person <where> ${ew.customSqlSegment} </where> </select>
调用
customSelectVoList
并结合PageHelper:PageHelper.startPage(pageNum, pageSize); List<DataPersonVO> oldPersons = mapper.customSelectVoList(wrapper); PageInfo<DataPersonVO> pageInfo = new PageInfo<>(oldPersons);
这种方式可以确保分页效果和分页信息正常显示,但需要手动定义SQL语句。
方案三:使用selectList
替代selectVoList
若不需要使用selectVoList
方法,可以直接使用MyBatis Plus的selectList
方法。selectList
方法与PageHelper兼容性更高,能正确生成PageInfo
分页数据。
PageHelper.startPage(pageNum, pageSize); List<DataPersonVO> oldPersons = mapper.selectList(wrapper); PageInfo<DataPersonVO> pageInfo = new PageInfo<>(oldPersons);
此方法与PageHelper的兼容性更高,PageInfo
的分页信息显示也更准确。
方案四:手动分页
在数据量较小的场景下,可以选择手动分页,不依赖分页插件。具体做法是:
不使用分页插件,直接查询符合条件的所有数据。
手动计算分页偏移量,从结果集中截取分页数据。
List<DataPersonVO> oldPersons = mapper.selectVoList(wrapper); int fromIndex = (pageNum - 1) * pageSize; int toIndex = Math.min(fromIndex + pageSize, oldPersons.size()); List<DataPersonVO> pagedResult = oldPersons.subList(fromIndex, toIndex);
手动分页适用于小数据量展示,但不适合大数据量场景。
总结
在MyBatis Plus和PageHelper联合使用时,使用MyBatis Plus的扩展方法(如selectVoList
)会导致PageHelper生成的PageInfo
信息不准确。以下为总结的几种解决方案:
使用MyBatis Plus自带分页插件:推荐方案,与
selectVoList
等扩展方法兼容性更好,能直接返回正确分页信息。自定义Mapper方法:可通过编写SQL语句避免MyBatis Plus扩展方法,确保PageHelper分页生效。
使用selectList替代selectVoList:若数据结构允许,
selectList
能与PageHelper更好兼容。手动分页:适用于小数据量分页展示,但不适合大数据量。
通过合理选择适合的方案,可以有效避免分页信息不准确的问题,提高代码的稳定性和兼容性。希望本文能够帮助大家在项目开发中更好地应用MyBatis Plus与PageHelper,避免类似的分页问题。