如何使用
直接导入依赖
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
常见的使用方式
public PageInfo findPage(int pageNum,int pageSize){
PageHelper.startPage(pageNum,pageSize);
List<User> list=userDao.selectAll();
PageInfo pageInfo = new PageInfo(list);
return pageInfo;
}
说明
startPage()
方法调用后必须紧跟 MyBatis 查询方法startPage()
方法是静态方法, 只需要传入pageNum
和pageSize
两个参数- 我们不需要对查询 SQL 做修改就可以达到分页的效果
- PageInfo 里面包含了一整个页面的信息
- PageInfo 构造函数传入的参数必须是
startPage()
后的那个方法得到的对象(原因下文解释)
PageInfo 中的参数说明
public class PageInfo<T> extends PageSerializable<T> {
// 当前页的页码
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<T>
public class PageSerializable<T> implements Serializable {
private static final long serialVersionUID = 1L;
// 当前页的记录条数
protected long total;
// 当前页的每一条记录
protected List<T> list;
// 方法省略
}
PageHelper 使用中的坑
需求描述
出于安全性的考虑, 我想要查询到的 POJO 映射到 VO 类中,VO 类相比 POJO 类缺少了某些私密属性, 将 VO 作为基本元素封装到 PageInfo 中, 于是我写出来如下代码
PageInfo<PostItemVO> selectAll() {
// 开启分页 (PageNum,PageSize)
PageHelper.startPage(1, 2);
List<Post> posts = postMapper.selectAll();
// 属性拷贝
List<PostItemVO> postItemVOS = new ArrayList<>();
for (Post post : posts) {
PostItemVO postItemVO = new PostItemVO();
BeanUtils.copyProperties(post,postItemVO);
postItemVOS.add(postItemVO);
}
// PageInfo 封装
PageInfo<PostItemVO> pageInfo = new PageInfo<PostItemVO>(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<Post> posts = postMapper.selectAll();
// 直接将Post封装
PageInfo pageInfo = new PageInfo<>(posts);
// 取出List进行数据转移
ArrayList<PostItemVO> 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
进行修改
<!--结果映射-->
<resultMap id="ItemMap" type="im.yzh.mymyblog.model.vo.PostItemVO">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="title" jdbcType="VARCHAR" property="title" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="published" jdbcType="BIT" property="published" />
<result column="category_id" jdbcType="BIGINT" property="categoryId" />
</resultMap>
<!--一共有哪些字段-->
<sql id="Item_Column_List">
id, title, update_time, published, category_id
</sql>
<!--查询SQL-->
<select id="selectAllItem" resultMap="ItemMap">
select <include refid="Item_Column_List"/>
from post order by update_time desc
</select>
2 在 PostMapper 接口中添加相关方法
List<PostItemVO> selectAllItem();
3 编写测试
PageInfo<PostItemVO> selectAllItem() {
PageHelper.startPage(1, 2);
List<PostItemVO> posts = postMapper.selectAllItem();
PageInfo<PostItemVO> pageInfo = new PageInfo<PostItemVO>(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不对