文章目录

  • 一、分页查询概述
    • 1.1、分页查询分类
      • 1.1.1、真分页
      • 1.1.2、假分页
    • 1.2、分页效果
  • 二、分页的设计
    • 2.1、分页需要传递的参数
      • 2.1.1、用户需要传入的参数
      • 2.1.2、分页需要展示的数据
      • 2.1.3、分页需展示的数据的来源
    • 2.2、分页原理
  • 三、分页查询实现
    • 3.1、访问流程
    • 3.2、分页参数的封装
    • 3.3、编写PageResult
    • 3.4、修改Mapper(Dao)
    • 3.5、修改Service以及ServiceImpl
    • 3.6、编写QueryObject
    • 3.7、编写测试类
    • 3.7、编写Servlet
    • 3.7、前台实现

一、分页查询概述

分页查询则是在页面上将本来很多的数据分段显示,每页显示用户自定义的行数。可提高用户体验度,
    同时减少一次性加载,内存溢出风险。

1.1、分页查询分类

1.1.1、真分页

每次翻页从数据库中查询数据。

  1. 优点:不容易造成内存溢出。
  2. 缺点:实现复杂,性能相对低。

1.1.2、假分页

一次性查询所有数据存入内存,翻页从内存中获取数据。

  1. 优点:实现简单,性能高。
  2. 缺点:容易造成内存溢出。

1.2、分页效果

发送请求访问一个带有分页页面的数据,会发现其主要由两部分组成:

  1. 当前页的结果集数据,比如这一页有哪些商品信息。
  2. 分页条信息,比如包含【首页】【上页】【下页】【末页】等。

二、分页的设计

2.1、分页需要传递的参数

2.1.1、用户需要传入的参数

  1. currentPage:当前页,跳转到第几页,int 类型,设置默认值,比如 1。
  2. pageSize:每页最多多少条数据,int 类型,设置默认值,比如 10。

2.1.2、分页需要展示的数据

  1. start:首页。
  2. prevPage:上一页。
  3. nextPage:下一页。
  4. totalPage:末页页码。
  5. totalCounts:总记录数。
  6. currentPage:当前页。
  7. pageSize:每页记录数。

2.1.3、分页需展示的数据的来源

  • 来源于用户传入:

    1. currentPage: 当前页,int 类型。

    2. pageSize: 每页显示多少条数据,int 类型。

  • 来源于两条 SQL 查询:

    1. totalCount/rows: 数据总条数,int 类型。
    2. data/list: 每一页的结果集数据,List 类型。
  • 来源于程序计算:

    1. totalPage: 总页数/末页,int 类型。
    2. prevPage: 上一页,int 类型。
    3. nextPage: 下一页,int 类型。

2.2、分页原理

结果总数(totalCount/rows)和结果集(data/list)是来源于两条 SQL:

  1. 第一条SQL:查询总数,返回一个数字(总记录数)。
select count(*) from province
  1. 查询符合条件的结果集(返回一个结果集)。
# 他有两个参数,一个是起始页的页码,另一个是每页记录数
# start :(currentPage - 1) * pageSize
# pageSize: 前台给予
select * from province limit #{start} ,#{pageSize}
  1. 计算出其余的参数(总页数、上一页、下一页)
  // 分页数据通过这个构造器封装好public PageResult(int currentPage, int pageSize, int totalCount, List<T> data) {this.currentPage = currentPage;this.pageSize = pageSize;this.totalCount = totalCount;this.data = data;// 计算总页数(要先算)this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;// 利用三元运算符来计算上一页,如果已经是第一页的话,那么他就不会有上一页,让他的上一页为第一页,否则就当前页减1为上一页this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;// 利用三元运算符计算下一页,如果已经是最后一页的话,那么就没有下一页了,就不让他下一页再增加,否则就当前页自增this.nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;}

三、分页查询实现

3.1、访问流程

3.2、分页参数的封装

为了能在页面上显示上述的分页效果,那么我们就得在把页面上的每一个数据封装成到某个对象共享给

JSP。

如果我们不进行封装的话,那么这个七个参数要全部在Session域中去取,比较复杂和恶心。

我们一般会把多个需要共享的数据,封装到一个对象,往后就只需要把数据封装到该对象,再共享该对象即可。

3.3、编写PageResult

package com.qo;import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor/**封装结果数据(某一页的数据)* @author Xiao_Lin*/
public class PageResult<T> {// 用户输入的数据private int currentPage;  // 当前页码private int pageSize; // 每页显示的条数//SQL执行后的结果private int totalCount; // 总条数private List<T> data; // 当前页数据结果集// 利用程序计算出来的private int prevPage; // 上一页private int nextPage; // 下一页private int totalPage; // 最后一页// 分页数据通过这个构造器封装好public PageResult(int currentPage, int pageSize, int totalCount, List<T> data) {this.currentPage = currentPage;this.pageSize = pageSize;this.totalCount = totalCount;this.data = data;// 计算总页数(要先算)this.totalPage = totalCount % pageSize == 0 ? totalCount / pageSize : totalCount / pageSize + 1;// 利用三元运算符来计算上一页,如果已经是第一页的话,那么他就不会有上一页,让他的上一页为第一页,否则就当前页减1为上一页this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;// 利用三元运算符计算下一页,如果已经是最后一页的话,那么就没有下一页了,就不让他下一页再增加,否则就当前页自增this.nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;}
}

3.4、修改Mapper(Dao)

 // 查询总记录数,传入一个封装好的查询对象,里面的参数有当前页、每页记录数(可不传,尽量传,为模糊查询做基础)int queryCount(QueryObject qo);// 查询结果集,传入一个封装好的查询对象,里面封装好的参数有当前页、每页记录数、起始页页码List<Province> query(QueryObject qo);

3.5、修改Service以及ServiceImpl

  PageResult<Province> query(ProvinceQueryObject qo);
package com.service.impl;/*** @author Xiao_Lin* @date 2021/1/22 22:25*/
public class ProvinceServiceImpl implements ProvinceService {ProvinceMapper mapper = ConnUtils.getConnection().getMapper(ProvinceMapper.class);@Overridepublic PageResult<Province> query(ProvinceQueryObject qo) {// 获取查询的记录数int totalCount = mapper.queryCount(qo);// 如果总记录数为0,那么说明没数据就不用下一步查询了,提高效率。if (totalCount == 0){// 返回一个查询结果集,返回当前页、每页记录数、以及一个空的结果集return new PageResult<Province>(qo.getCurrentPage(),qo.getPageSize(),totalCount,Collections.EMPTY_LIST);}// 记录数不为0,查询出一个结果集List<Province> provinces = mapper.query(qo);// 返回一个查询结果集,返回当前页、每页记录数、以及结果集return new PageResult<Province>(qo.getCurrentPage(),qo.getPageSize(),totalCount,provinces);}

3.6、编写QueryObject

package com.domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 封装分页查询需要的两个请求传入的分页参数* @author Xiao_Lin* @date 2021/1/22 21:49*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QueryObject {private int currentPage = 1; // 当前页码,要跳转到哪一页的页码(需要给默认值)private int pageSize = 3 ; // 每页显示条数(需要给默认值)//用于 Limit 子句第一个 ? 取值,起始页页码public int getStart(){return (currentPage-1)*pageSize;}
}

3.7、编写测试类

 ProvinceService provinceService = new ProvinceServiceImpl();QueryObject qo = new QueryObject();PageResult<Province> pageResult = provinceService.query(qo);System.out.println("当前页:"+pageResult.getCurrentPage());System.out.println("结果集数据:" + pageResult.getData());System.out.println("当前页总记录数:" + pageResult.getTotalCount());System.out.println("条数:" + pageResult.getData().size());System.out.println("总页数:" + pageResult.getTotalPage());System.out.println("上一页:" + pageResult.getPrePage());System.out.println("下一页:" + pageResult.getNextPage());

3.7、编写Servlet

package com.servlet;/*** @author Xiao_Lin* @date 2021/1/24 10:17*/
@WebServlet(urlPatterns = "/listall")
public class ProvinceServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {ProvinceService provinceService = new ProvinceServiceImpl();// 创建QueryObject对象QueryObject qo = new QueryObject();// 获取参数String currentPage = req.getParameter("currentPage");// 利用工具类判断是否传了这个参数if (StringUtil.hasLength(currentPage)){// 如果传了就赋值qo.setCurrentPage(Integer.parseInt(currentPage));}String pageSize = req.getParameter("pageSize");if (StringUtil.hasLength(pageSize)){qo.setPageSize(Integer.parseInt(pageSize));}// 调用业务层方法来处理请求查询某一页数据PageResult<Province> query = provinceService.query(qo);// 把数据共享给jspreq.setAttribute("pageResult", query);// 控制跳转到 list.jsp 页面req.getRequestDispatcher("/WEB-INF/views/product/list.jsp").forward(req, resp);}
}

3.7、前台实现

包含编写 Servlet 及 JSP,Servlet 处理请求,调用业务方法,把查询到数据共享到 JSP 中,展示给用户。操作步骤:

  1. 浏览器发出分页请求参数(去往第几页/每页多少条数据),在 Servlet 中接收这些参数,并封装
    到 QueryObject 对象,调用 Service 中分页查询方法(query)。
  2. 把得到的分页查询结果对象(PageResult)共享在请求作用域中,跳转到 JSP,显示即可。
  3. 修改 JSP 页面,编写出分页条信息(分页条中的信息来源于 PageResult 对象)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>产品列表</title><script type="text/javascript">window.onload = function () {var trClzs = document.getElementsByClassName("trClassName");for(var i = 0; i < trClzs.length; i++){trClzs[i].onmouseover = function () {console.log(1);this.style.backgroundColor = "gray";}trClzs[i].onmouseout = function () {console.log(2);this.style.backgroundColor = "";}}}// 分页 JSfunction changePageSize() {document.forms[0].submit();}</script>
</head>
<body><form action="/product"><table border="1" cellspacing="0" cellpadding="0" width="80%"><tr><th>编号</th><th>名称</th><th>简称</th></tr><c:forEach var="province" items="${pageResult.data}"varStatus="status"><tr class="trClassName"><td>${status.count}</td><td>${province.id}</td><td>${province.name}</td><td>${province.abbr}</td><td><a href="/listall?cmd=delete&id=${product.id}">删除</a><a href="/listall?cmd=input&id=${product.id}">修改</a></td></tr></c:forEach><tr align="center"><td colspan="9"><a href="/listall?currentPage=1">首页</a><a href="/listall?currentPage=${pageResult.prevPage}">上一页</a><a href="/listall?currentPage=${pageResult.nextPage}">下一页</a><a href="/listall?currentPage=${pageResult.totalPage}">尾页</a>当前第 ${pageResult.currentPage} / ${pageResult.totalPage} 页一共 ${pageResult.totalCount} 条数据跳转到<input type="number" οnchange="changePageSize()"name="currentPage" value="${pageResult.currentPage}" style="width: 60px;">页每页显示<select name="pageSize" οnchange="changePageSize()"><option value="3" ${pageResult.pageSize == 3 ?'selected' : ''}> 3 </option><option value="5" ${pageResult.pageSize == 5 ?'selected' : ''}> 5 </option><option value="8" ${pageResult.pageSize == 8 ?'selected' : ''}> 8 </option></select>条数据</td></tr></table>
</form>
</body>
</html>

原生分页查询原理步骤解析相关推荐

  1. 用了这么久的PageHelper,你知道原生的分页查询原理和步骤吗

    你知道的越多,不知道的就越多,业余的像一棵小草! 成功路上并不拥挤,因为坚持的人不多. 编辑:业余草 juejin.cn/post/6987553953156169742 推荐:https://www ...

  2. oracle游标多线程,多线程jdbc游标分页查询原理 oracle和mysql分页

    分页查询中如何使用多线程加快处理速度? 分页sql是拼起来的现在怎么优化可以提高展示速度:优化思路: 1.试试并发多线程访问,然后把多线程获取的结果合并在一起. 2.做索引,加快查询速度. 3.把经常 ...

  3. pageHelper与PageInfo联合进行分页查询原理

    示例代码 : 此条查询语句会被分页处理, 返回对应的结果集数据, 即users集合 question : 既然进行了分页处理, 那怎么获取数据的总条数呢? 其实users集合其实是Page对象, Pa ...

  4. redis锁原理步骤解析

    redis高并发锁原理: 1.用一个常量拼接当前用户的ID作为key,当前时间戳加上锁超时时间作为value 2.进入一个while死循环 3.循环内第一个判断利用redis的一个方法setIfAbs ...

  5. Mybatis一对多分页查询问题

    一.背景引入 Mybatis提供了处理结果集的标签,其中子标签collection可以处理1对多的映射 <resultMap><collection></collecti ...

  6. SpringBoot+VUE前后端分离项目学习笔记 - 【08 SpringBoot实现分页查询】

    手动实现分页功能 先理解分页查询原理 采用limit语句来实现分页 -- 页码PageNum 每页数据条目PageSize=5 -- 第一页 PageNum=0, limit 0,5 SELECT * ...

  7. mysql中如何分页查询_MySQL_mysql分页原理和高效率的mysql分页查询语句,以前我在mysql中分页都是用的 l - phpStudy...

    mysql分页原理和高效率的mysql分页查询语句 以前我在mysql中分页都是用的 limit 100000,20这样的方式,我相信你也是吧,但是要提高效率,让分页的代码效率更高一些,更快一些,那我 ...

  8. 记一次SpringDateJpa 使用原生sql 分页查询

    jpa 如果使用原生sql如何分页查询呢? @GetMapping("/getInfo")public Result getOpenId() throws Exception{Si ...

  9. ElasticSearch分页查询四种解决方案与原理

    当你拼命想完成一件事的时候,你就不再是别人的对手,或者说得更确切一些,别人就不再是你的对手了,不管是谁,只要下了这个决心,他就会立刻觉得增添了无穷的力量,而他的视野也随之开阔了.--<基督山伯爵 ...

最新文章

  1. 《深入理解Java虚拟机》(第二版)学习2:垃圾收集算法
  2. mysql自增变量插入行时需要赋值
  3. BS程序代码与安全与基本攻击/防御模式
  4. 身为Java程序员,这些开源工具你一定要学会!
  5. 天融信防火墙NGFW4000配置
  6. Oracle入门(十二B)之表创建
  7. 用python做自我介绍_python入门教程NO.2 用python做个自我介绍
  8. 2021届安徽高考成绩查询,安徽2021年高考成绩什么时候公布
  9. R_地图上的迷你直方图
  10. steam常用计算机,絮絮叨叨的繁星 篇二:新电脑必备——常用验机和跑分软件汇总...
  11. win10家庭版设置本地策略组
  12. 关于空间风靡的心理入侵小游戏浅析
  13. 微信小程序下拉刷新功能--onPullDownRefresh
  14. HTML5教程7-实战:调色板
  15. 4200: [Noi2015]小园丁与老司机
  16. MSF-Evasion模块免杀
  17. 电脑或网页打开很慢是什么原因?
  18. 计算机网络启动不了怎么办,网络适配器无法启动如何修复_网络适配器不能启动的处理办法-系统城...
  19. php 项目创意,JavaScript实现“创意时钟”项目
  20. 大数据剖析:想与北上争雄,深圳到底还差在哪儿?

热门文章

  1. Headless Services无头服务
  2. GitHub获百万下载的阿里P5-P9必刷知识体系图核心手册
  3. 运筹学 ——线性规划之单纯形法
  4. 数据安全治理体系与技术研究
  5. OneApiConnect(二)三菱MC通讯协议源代码,高效稳定
  6. 现代化城市智慧管廊综合管理系统建设方案简介
  7. 小商品销售平台+后台管理系统(day2-day5)练习小项目~
  8. 最长不重复子串(java)
  9. 小程序界面开发实现各种机型自适应
  10. 用python在网页上爬【微博】用户发的微博(json解析)