先知道怎么手写一个分页查询,再去使用 PageHelper 吧
select * from tableName limit offset size
这条语句的含义是:从 tableName 表中的第 offset 条记录开始(注意 offset 从零开始),查询出 size 个记录。
举个例子,category 表中数据如下:
运行下边这条语句:查询从第 2 条记录(即 id = 3)开始的连续 5 条记录
select * from category limit 2, 5;
3. 承载分页信息的实体类
分页信息实体类包含如下数据:
是否显示上一页按钮 showPrevious
是否显示下一页按钮 showNext
是否显示跳转到第一页按钮 showFirstPage
是否显示跳转到最后一页按钮 showEndPage
当前页码 pageNumber
当前页可跳转的页码列表 pageNumbers
总页码数 totalPage
当前页要显示的具体数据
/**
分页所需要的信息*/public class PaginationDTO {private boolean showPrevious; // 是否显示上一页按钮 private boolean showNext; // 是否显示下一页按钮 private boolean showFirstPage; // 是否显示跳转到第一页按钮 private boolean showEndPage; // 是否显示跳转到最后一页按钮
private Integer pageNumber; // 当前页码 private List<Integer> pageNumbers = new ArrayList<>(); // 当前页可跳转的页码列表 private Integer totalPage; // 总页码数
private List<Question> questionList; // 当前页要显示的具体数据
// Getter and Setter
4. 根据当前页码设置分页所需要的信息
这段代码做的事情就是我们在第 1 节分析的,决定上一页、下一页、第一页和最后一页按钮是否显示。
显然,这段代码应该放在承载分页信息的实体类 PaginationDTO 中:
/**
分页所需要的信息*/@Datapublic class PaginationDTO {
......
/**
根据当前页码设置相关分页信息
@param totalPage 页码总数
@param pageNumber 当前页码*/public void setPagination(Integer totalPage, Integer pageNumber) {this.totalPage = totalPage;this.pageNumber = pageNumber;
// 页码列表的显示:显示当前页和当前页的前三页和后三页,可为空 pageNumbers.add(pageNumber);for (int i = 1; i <= 3; i++) {if (pageNumber - i > 0) {pageNumbers.add(0, pageNumber - i);}
if (pageNumber + i <= totalPage) {pageNumbers.add(pageNumber + i);}}
// 是否展示上一页按钮 if (pageNumber == 1) {showPrevious = false;}else {showPrevious = true;}// 是否展示下一页按钮 if (pageNumber.equals(totalPage)) {showNext = false;}else {showNext = true;}
// 是否展示跳转到第一页按钮 if (pageNumbers.contains(1)) {// 如果当前页可跳转的页码列表包含第一页,则不展示跳转到第一页按钮 showFirstPage = false;}else {showFirstPage = true;}// 是否展示跳转到最后一页按钮 if (pageNumbers.contains(totalPage)) {// 如果当前页可跳转的页码列表包含最后一页,则不展示跳转到最后一页按钮 showEndPage = false;}else {showEndPage = true;}}}
5. 分页查询请求入口
Controller 层:
@Controllerpublic class IndexController {
@Autowiredprivate QuestionService questionService;
/**
@param request
@param model
@param pageNumber 第多少页,默认第 1 页
@param pageSize 每页显示的问题数量, 默认为 10
@return*/@GetMapping("/")public String index(HttpServletRequest request, Model model,@RequestParam(name = "pageNumber", defaultValue = "1") Integer pageNumber,@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
.........
// 获取问题列表需要的信息 PaginationDTO pagination = questionService.list(pageNumber, pageSize);model.addAttribute("pagination", pagination);
......}}
对应的前端:(Thymeleaf 模板引擎),利用 th:each 标签循环页码列表,然后在 url 后面加上 pageNumber,使得后端能够通过 RequestParam 获取到当前页码
<li th:each="pageNumber : {pagination.pageNumber == pageNumber}? 'active' : ''"><a th:href="@{/(pageNumber = {pageNumber})}" th:text="{pageNumber}"></a></li>
上一页、下一页、第一页和最后一页按钮的前端代码就不贴了,大同小异。
QuestionService 如下
6. 分页查询
前面说过,页面承载的信息是 Question,我们建立一个 QuestionService.list 方法 用于分页查询,具体包含:
页码总数 totalPage 的计算
页码列表的容错处理。比如总页码只有 8 页,但是我们在地址栏手动修改为 12 页,我们需要它在分页栏高亮最后一页并显示最后一页数据,而不是第 12 页,第 12 页是不存在的。
分页查询数据。涉及每页起始索引的计算
第 1 页:起始索引 0,limit 0, 10
第 2 页:起始索引 10,limit 10, 20
第 3 页:起始索引 30,limit 20, 30
......
推出 => 若当前页码为 i,每页显示 10 条数据,则每页的起始索引 offset = 10 * (i - 1)
@Servicepublic class QuestionService {
@Autowiredprivate QuestionMapper questionMapper;
/**
分页查询
@param pageNumber 第多少页(当前页码)
@param pageSiz
e 每页显示的问题数量
@return*/
评论