大型项目中获取数据的体量一般很大,在前段界面进行展示时为了保障展示效果,会要求接口快速返回,这时候后端一般会选择分页获取数据,只传递要查询的页码数据就可以。这种情况就避免了大部分的问题,达到快速返回的效果。
现阶段常用的分页有两种:
MyBatis
分页插件:PageHelper
,这个插件很常用,支持多数据库分页,无需修改SQL语句即可实现分页功能。- 注意:这个插件的功能相当于在你代码中的第一个 SQL 语句的后面加上
LIMIT [offset], [limit]
子句,例如LIMIT 20, 10
,表示从21条记录开始,获取10条记录。 - 这个插件
只会在你的第一条语句后面添加子句
,如果代码后面还存在其他的 SQL 则会不生效。 - 如果你使用这个插件获取
UserId
列表,并用该列表进行后续操作,要注意返回的顺序问题 。 - 详细了解请查看文章:SpringBoot 项目如何使用 MyBatis 的分页插件 PageHelper 做分页处理
- 注意:这个插件的功能相当于在你代码中的第一个 SQL 语句的后面加上
- 手动分页:
PageInfo
类。这个类也是MyBatis
分页插件中的类,只不过是手动赋值。- 手动分页适合数据量小的情况,因为需要预先加载所有数据,例如预先加载所有
UserId
,对UserId
进行划分数量,根据请求的分页参数查询处在不同数量位置的UserId
。
- 手动分页适合数据量小的情况,因为需要预先加载所有数据,例如预先加载所有
本文只介绍分页类 PageInfo
,包括创建方式,代码示例和验证结果展示等。
文章目录
一、分页信息封装类 PageInfo 是什么?
我们在使用 MyBatis 分页时,不论是使用自动分页还是手动分页都会使用 PageInfo 对象作为承接介质。
PageInfo 是一个分页信息封装类,通常用于Web应用中的分页数据展示。它可以将分页查询结果和分页参数封装在一个对象中,便于传输和使用。我们使用时会遇到以下属性:
1、存储和管理分页相关的参数,自动分页时会自动设置,而手动分页时需要手动设置。
当前页码(pageNum
)、每页记录数(pageSize
)、总记录数(total
)、总页数(pages
)
2、分页导航信息参数
是否有上一页(hasPreviousPage
)、是否有下一页(hasNextPage
)、是否为第一页(isFirstPage
)、是否为最后一页(isLastPage
)、导航页码数组(navigatepageNums
)
3、PageInfo 作为后端返回给前端的标准分页数据格式,便于前端渲染分页组件。前端在使用时无需手动计算分页参数,如总页数、是否有下一页等,提高可读性和可维护性。
二、使用 pagehelper-spring-boot-starter 依赖引入
上篇文章 SpringBoot 项目如何使用 MyBatis 的分页插件 PageHelper 做分页处理 详细讲解了关于分页插件的依赖引用,这次只介绍一个大家最常使用的依赖。
SpringBoot 起步依赖封装了关于分页插件的依赖,需要在配置文件 application.properties
或 application.yml
中进行配置。
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
配置文件内容:
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
三、创建示例展示使用分页插件
1、创建数据库表格示例
本文创建一个 tb_user
表,含有 id
、username
和password
字段。本文只做一个简单示例,不涉及复杂业务。
使用 pagehelper-spring-boot-starter
依赖时进行的分页条件配置。
pagehelper:
helper-dialect: mysql
reasonable: true // 规整页码范围
support-methods-arguments: true // 规整方法参数获取
下面代码中存在部分代码是项目中必须代码,如统一封装返回,MyBatis
项目搭建等就不在本文展示,有兴趣可查看以下文章。
关于统一 API 响应结果封装,代码示例在 SpringBoot 项目统一 API 响应结果封装 。
关于 MyBatis
的项目搭建在 SpringBoot 项目整合 MyBatis 框架 。
2、PageInfoController
package com.wen.controller;
import com.wen.data.Result;
import com.wen.data.ResultGenerator;
import com.wen.service.PageInfoService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/pageInfoTest")
public class PageInfoController {
@Autowired
private PageInfoService pageInfoService;
@GetMapping("/select")
public Result<?> selectUserByPage(@Param("pageSize") Integer pageSize, @Param("pageNumber") Integer pageNumber) {
return ResultGenerator.genSuccessResult(pageInfoService.selectUserByPage(pageSize, pageNumber));
}
}
3、PageInfoService
package com.wen.service;
import com.github.pagehelper.PageInfo;
import com.wen.dto.TbUser;
public interface PageInfoService {
PageInfo<TbUser> selectUserByPage(Integer pageSize, Integer pageNumber);
}
4、PageInfoServiceImpl
package com.wen.service.impl;
import com.github.pagehelper.PageInfo;
import com.wen.dto.TbUser;
import com.wen.mapper.TbUserMapper;
import com.wen.service.PageInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class PageInfoServiceImpl implements PageInfoService {
@Autowired
private TbUserMapper tbUserMapper;
@Override
public PageInfo<TbUser> selectUserByPage(Integer pageSize, Integer pageNumber) {
// 1、先获取业务中使用所用ID等参数,用于确定返回顺序
List<Integer> tbUserId = tbUserMapper.selectUserId();
// 2、计算查询到的用户的总记录数
int totalCount = tbUserId.size();
// 3、手动分页,获取其中选取页的用户数据
int start = (pageNumber - 1) * pageSize;
int end = Math.min(start + pageSize, totalCount);
// 4、分页过后需要查询获得数据的id
List<Integer> pageId = tbUserId.subList(start, end);
List<TbUser> tbUsers = tbUserMapper.selectUserByIdList(pageId);
// 5、构建分页结果
PageInfo<TbUser> pageInfo = new PageInfo<>(tbUsers);
// 6、参数填写,用户传递给前端
pageInfo.setTotal(totalCount);
pageInfo.setPageNum(pageNumber);
pageInfo.setPageSize(pageSize);
return pageInfo;
}
}
5、TbUserMapper
package com.wen.mapper;
import com.wen.dto.TbUser;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface TbUserMapper {
List<Integer> selectUserId();
List<TbUser> selectUserByIdList(@Param("idList") List<Integer> idList);
}
6、TbUserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wen.mapper.TbUserMapper">
<select id="selectUserId" resultType="java.lang.Integer">
SELECT id FROM tb_user
</select>
<select id="selectUserByIdList" resultType="com.wen.dto.TbUser">
SELECT username, password FROM tb_user Where
<if test="idList.size() > 0">
id in
<foreach collection="idList" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</select>
</mapper>
三、手动分页插件的结果展示
手动分页和使用自动分页插件展示的结果一样。
http://localhost:8080/pageInfoTest/select?pageSize=2&pageNumber=1
由下面的 JSON 结果可以看到数据的总数,页数,每页数据数量等,还有导航页面数据。
{
"code": 1,
"message": "SUCCESS",
"data": {
"total": 6,
"list": [
{
"id": 0,
"username": "laowang",
"password": "112233"
},
{
"id": 0,
"username": "zhangsan",
"password": "221133"
}
],
"pageNum": 1,
"pageSize": 2,
"size": 2,
"startRow": 0,
"endRow": 1,
"pages": 1,
"prePage": 0,
"nextPage": 0,
"isFirstPage": true,
"isLastPage": true,
"hasPreviousPage": false,
"hasNextPage": false,
"navigatePages": 8,
"navigatepageNums": [
1
],
"navigateFirstPage": 1,
"navigateLastPage": 1
}
}