关于 PageHelper 分页插件的使用以及其中的坑 | 您所在的位置:网站首页 › pagehelper分页使用第二个sql分页 › 关于 PageHelper 分页插件的使用以及其中的坑 |
如何使用
直接导入依赖 com.github.pagehelper pagehelper-spring-boot-starter 1.2.13常见的使用方式 public PageInfo findPage(int pageNum,int pageSize){ PageHelper.startPage(pageNum,pageSize); List list=userDao.selectAll(); PageInfo pageInfo = new PageInfo(list); return pageInfo; }说明 startPage() 方法调用后必须紧跟 MyBatis 查询方法 startPage() 方法是静态方法, 只需要传入 pageNum 和 pageSize 两个参数 我们不需要对查询 SQL 做修改就可以达到分页的效果 PageInfo 里面包含了一整个页面的信息 PageInfo 构造函数传入的参数必须是 startPage() 后的那个方法得到的对象(原因下文解释) PageInfo 中的参数说明 public class PageInfo extends PageSerializable { // 当前页的页码 private int pageNum; // 页大小, 为分页时提供的参数 private int pageSize; // 当前页的记录条数 private int size; // 由第几条开始(数据库行号) private int startRow; // 第几条结束(数据库行号) private int endRow; // 一共有多少页 private int pages; // 前一页的页号, 如果没有前一页就是为0 private int prePage; // 后一页的页号, 如果没有前一页就是为0 private int nextPage; // 是否是第一页 private boolean isFirstPage; // 是否是最后一页 private boolean isLastPage; // 是否有前一页 private boolean hasPreviousPage; // 是否有后一页 private boolean hasNextPage; // 每页显示的页码个数, 在构造方法里面被默认设置为8 private int navigatePages; // 页码数 private int[] navigatepageNums; // 首页 private int navigateFirstPage; // 尾页 private int navigateLastPage; // 方法省略 }另外它还继承自 PageSerializable public class PageSerializable implements Serializable { private static final long serialVersionUID = 1L; // 当前页的记录条数 protected long total; // 当前页的每一条记录 protected List list; // 方法省略 } PageHelper 使用中的坑 需求描述出于安全性的考虑, 我想要查询到的 POJO 映射到 VO 类中,VO 类相比 POJO 类缺少了某些私密属性, 将 VO 作为基本元素封装到 PageInfo 中, 于是我写出来如下代码 PageInfo selectAll() { // 开启分页 (PageNum,PageSize) PageHelper.startPage(1, 2); List posts = postMapper.selectAll(); // 属性拷贝 List postItemVOS = new ArrayList(); for (Post post : posts) { PostItemVO postItemVO = new PostItemVO(); BeanUtils.copyProperties(post,postItemVO); postItemVOS.add(postItemVO); } // PageInfo 封装 PageInfo pageInfo = new PageInfo(postItemVOS); return pageInfo; }Post 是我的 POJO, PostVO 是对应的 VO 类。数据库中查询得到 Post 集合,将其属性拷贝到 PostVO 集合。 乍一看其实写的不存在问题,但是我们在查询时就会出现问题 数据库表如下, 共有四条记录 得到的 PageInfo 如下
数据库中共有 4 条记录, 但是查询得到的 total 只有 2 条, 除此之外 nextPage,endRow…. 字段都出现了问题。 解决方法 方法一先直接将查询结果封装到一个 PageInfo 中, 之后将将该 PageInfo 的 list 取出来做改造 PageInfo< selectAll() { PageHelper.startPage(1, 2); List posts = postMapper.selectAll(); // 直接将Post封装 PageInfo pageInfo = new PageInfo(posts); // 取出List进行数据转移 ArrayList postItemVOS = new ArrayList(); pageInfo.getList().forEach(post->{ PostItemVO postItemVO = new PostItemVO(); BeanUtils.copyProperties(post,postItemVO); postItemVOS.add(postItemVO); }); pageInfo.setList(postItemVOS); return pageInfo; }查询结果如下 方法二 推荐 更加优雅的方式 , 我们对查询语句进行改造, 使其直接返回一个 VO 集合,也就是说数据库表直接映射到 VO 上, 之后直接将该 List 封装在 PageInfo 之后, 直接返回就行了. 1 需要对 PostMapper.xml 进行修改 id, title, update_time, published, category_id select from post order by update_time desc2 在 PostMapper 接口中添加相关方法 List selectAllItem();3 编写测试 PageInfo selectAllItem() { PageHelper.startPage(1, 2); List posts = postMapper.selectAllItem(); PageInfo pageInfo = new PageInfo(posts); return pageInfo; }如果你有更好的解决方法欢迎留言评论。 原因分析 total 字段为例, 为什么正确的查询结果是 4, 但是用之前的错误查询方法的结果是 2。 先分析之前的错误查询方法的代码。 打个断点,我们发现,在 startPage() 调用之后, 随后的一个查询被进行了分页, 查询结果被封装为了一个 Page 对象:
查看 com.github.pagehelper.Page 源代码, Page 对象中包含了之后被封装到 PageInfo 中的信息:
也就是说, 我们的查询结果就已经包含了 PageInfo 之后需要的信息。查询得到的是一个 Page 实例,而不仅仅是一个 List, 所以说, 只对 posts进行 POJO 的拷贝是不够的, 这会丢失我们的分页信息。 对正确的查询过程进行调试分析: 1 被分页之后得到一个 Page 对象:
2 调用 PageInfo 构造函数会执行一个方法判断传入的参数是否为 Page 对象:
假如是之前的那种错误方法, 我们传入的是 List 对象, 那么 this.total就被初始化为了 List 的长度。 这就解释了为什么错误的方法得到的分页对象的 total 为 2 参考资料如何使用分页插件 PageHelper,从pageinfo 中取到的total不正确的处理。(史上最最最最最最详细l!!!)20fen的博客-CSDN博客pagehelper total不对 |
CopyRight 2018-2019 实验室设备网 版权所有 |