Java研学-分页查询

news2024/11/15 4:28:27

一 分页概述

1 介绍

  将大量数据分段显示,避免一次性加载造成的内存溢出风险

2 真假分页

① 真分页
  一次性查询出所有数据存到内存,翻页从内存中获取数据,性能高但易造成内存溢出
② 假分页
  每次翻页从数据库中查询数据,性能低,但不易造成内存溢出

二 分页设计

1 分页传递参数 – 需用户传入的参数

  currentPage:当前页,跳转到第几页,int类型,设置默认值,比如1

  pageSize:每页最多多少条数据,int类型,设置默认值,比如 5

2 分页展示数据 – 分页依赖数据(分页条)

  beginPage:首页
  prevPage:上一页
  nextPage:下一页
  totalPage:总页数/末页
  totalCount/rows:总条数
  currentPage:当前页
  pageSize:每页显示多少条数据

3 分页展示数据的来源

① 来源于用户传入:
  currentPage:当前页,int类型
  pageSize:每页显示多少条数据,int类型
② 来源于两条SQL查询:
  totalCount/rows:数据总条数,int类型
  data/list:每一页的结果集数据,List类型
③ 来源于程序计算:
  totalPage:总页数/末页,int类型
  prevPage:上一页,int类型
  nextPage:下一页,int类型

4 结果总条数与结果集

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

// 查询符合条件的结果总数(totalCount/rows)
SELECT COUNT(*)FROM 表名[WHERE 条件]

// 第一个?:从哪一个索引的数据开始查询(默认从0开始)
// 第二个?:查询多少条数据
SELECTFROM 表名[WHERE 条件]LIMIT ?,? 

  第二条SQL中的两个参数,第一个取值为(currentPage-1)* pageSize,第二个取值为pageSize,都来源于用户传递的参数

5 总页数与上下翻页

  总页数与上下翻页,来自程序计算

// 优先计算 totalPage 
int totalPage = rows % pagesize == 0 ? rows / pagesize : rows / pagesize +1; 
int prevpage = currentPage -1>=1 ? currentPage - 1:1;
int nextpage = currentPage +1 <= totalpage ? currentPage + 1: totalpage; 

三 分页实现(后台)

1 流程

分页流程

2 数据封装

  为实现流程效果,需将查询回的分页数据封装成一个对象传递给JSP,这样只需要共享一个对象即可

3 封装对象 – PageResult

@Setter
@Getter
public class PageResult<T> {
    //上一页
    private  Integer prevPage;
    //下一页
    private  Integer nextPage;
    //总条数
    private  Integer totalCount;
    //总页数
    private Integer totalPage;
    //当前页码
    private Integer currentPage;
    //每页显示条数
    private Integer pageSize;
    //查询的集合
    private List<T> list;
    /*初始化分页对象有参构造*/
    public  PageResult(Integer currentPage,Integer pageSize,Integer totalCount,List<T> list){
        this.currentPage=currentPage;
        this.pageSize=pageSize;
        this.totalCount=totalCount;
        this.list=list;
        //总页数=总条数/每页显示条数 当求模运算值不等于0的时候总页数加1
        this.totalPage=(this.totalCount%this.pageSize==0)?(this.totalCount/this.pageSize):(this.totalCount/this.pageSize+1);
        //上一页
        this.prevPage=(this.currentPage==1)?(1):(this.currentPage-1);
        //下一页
        this.nextPage=(this.currentPage==this.totalPage)?(this.totalPage):(this.currentPage+1);
    }
}

4 Dao层实现

  为实现分页Dao层需增加两个方法,一个是查询数据总量,一个查询当前页的数据

// 数据总量
int queryCount(int currentPage,int pageSize);
// 结果集
List<Employee> queryPage(int currentPage,int pageSize);

  MyBatis提供的操作方法传入执行SQL的参数只能是1个,此时两个参数需要传递两个分页实参,可以使用Map封装参数,或者使用JavaBean封装参数

5 封装分页参数 – QueryObject

@Setter
@Getter
public class QueryObject {
    private Integer currentPage=1;
    private Integer pageSize=3;
    public int getStart(){
      return   (currentPage-1)*pageSize;//计算查询的起始索引
    }
}

6 编辑对应的Dao接口

	// EmployeeDao
	/*查询总条数*/
	int queryCount(QueryObject qo);
	/*分页查询*/
	List<Employee> queryPage(QueryObject qo);

7 编辑Dao的实现类

	@Override
    public int queryCount(QueryObject qo) {
        return sqlSession.selectOne("cn.tj.mapper.EmployeeMapper.queryCount",qo);
    }
    @Override
    public List<Employee> queryPage(QueryObject qo) {
        return sqlSession.selectList("cn.tj.mapper.EmployeeMapper.queryPage",qo);
    }

8 编辑对应Mapper文件

	<!--查询总条数-->
    <select id="queryCount" resultType="int">
        SELECT count(*) from employee
    </select>
    <!--分页查询-->
    <select id="queryPage" resultType="Employee">
        SELECT * from employee limit #{start},#{pageSize}
    </select>

9 业务层实现

  Servlet调用时返回分页查询的结果,返回PageResult对象,形参类型为QueryObject

	// service层接口
	/*分页查询*/
	PageResult<Employee> queryByPage(QueryObject qo);
	// service层实现类
	/*分页查询*/
	@Override
	public PageResult<Employee> queryByPage(QueryObject qo) {
        //查询总条数
        int totalCount = employeeDao.queryCount(qo);
        if(totalCount==0){
            return new PageResult<>(qo.getCurrentPage(),qo.getPageSize(),
                    0, Collections.emptyList());
        }
        //查询分页集合
        List<Employee> list = employeeDao.queryPage(qo);
        //创建分页对象
        PageResult<Employee> pageResult=new PageResult<>(qo.getCurrentPage(),qo.getPageSize(),
                totalCount,list);
        return pageResult;
    }

四 分页实现(前台)

1 流程

  前台主要指Servlet及JSP,Servlet处理请求,调用业务方法,把查询到数据共享到JSP中,展示给用户看。
  浏览器发出分页请求参数(去往第几页/每页多少条数据),在Servlet中接收这些参数,并封装到QueryObject对象,调用Service中分页查询方法(query).
  把得到的分页查询结果对象(PageResult)共享在请求作用域中,跳转到JSP,显示即可。
  修改JSP页面,编写出分页条信息(分页条中的信息来源于PageResult 对象)。

2 EmployeeServlet

// 获取页面传递的分页参数,执行查询,将结果共享到请求作用域,请求转发回到list.jsp页面
@WebServlet("/employee")
public class EmployeeServlet extends HttpServlet {
    private EmployeeService employeeService=new EmployeeServiceImpl();
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码格式
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        // 登录权限判断 操作员工需要先登录
        HttpSession session = req.getSession();
        Users users = (Users) session.getAttribute("USER_IN_SESSION");
        if (users==null){//如果没有登录,跳转登录页面,给出提示
            req.setAttribute("msg","请先登录再操作!");
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
            return;
        }
        //获取请求分发的参数
        String cmd = req.getParameter("cmd");
        if ("delete".equals(cmd)){
            //调用删除
            delete(req,resp);
        }else if("input".equals(cmd)){
            //跳转到增加或修改页面
            input(req,resp);
        } else if("saveOrUpdate".equals(cmd)){
            //保存增加或修改
            saveOrUpdate(req,resp);
        }else{
            //查询所有
            list(req,resp);
        }
    }

    /*增加修改保存*/
    private void saveOrUpdate(HttpServletRequest req, HttpServletResponse resp) {
        //封装员工对象
        Employee employee=new Employee();
        /*将参数的获取及封装对象过程抽取成一个方法*/
        req2employee(req,employee);
        /*根据请求中是否携带id判断执行增加或者修改操作*/
        String id = req.getParameter("id");
        if (StringUtil.hasLength(id)){
            employee.setId(Long.valueOf(id));
            //执行修改
            employeeService.update(employee);
        }else{
            //调用dao方法执行增加保存操作
            employeeService.add(employee);
        }
        try {
            //跳转到查询
            resp.sendRedirect("/employee");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /*封装的获取请求参数的方法*/
    private void req2employee(HttpServletRequest req, Employee employee) {
        //获取请求中表单参数
        String name = req.getParameter("name");
        //验证输入的表单参数不能为空
        if (StringUtil.hasLength(name)){
            //编辑员工姓名
            employee.setName(name);
        }
        String salary = req.getParameter("salary");
        if (StringUtil.hasLength(salary)){
            employee.setSalary(Double.valueOf(salary));
        }
    }
    /*跳转到编辑页面*/
    private void input(HttpServletRequest req, HttpServletResponse resp) {
        //根据请求中是否携带id判断是增加或者修改操作
        String id = req.getParameter("id");
        if (StringUtil.hasLength(id)){//请求中携带了id执行修改
            //根据id查询员工
            Employee employee = employeeService.selectOne(Long.valueOf(id));
            //将查询的员工存储到作用域
            req.setAttribute("employee",employee);
        }
        try {
            //跳转到WEB-INF下面的页面:input.jsp
            req.getRequestDispatcher("/WEB-INF/views/employee/input.jsp").forward(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*分页查询所有*/
    private void list(HttpServletRequest req, HttpServletResponse resp) {
        try {
            /*客户端如果传入了当前页码和每页显示条数则设置给qo对象,如果没有传入则使用默认值*/
            String currentPage = req.getParameter("currentPage");
            String pageSize = req.getParameter("pageSize");
            QueryObject qo=new QueryObject();
            if (StringUtil.hasLength(currentPage)){
                qo.setCurrentPage(Integer.valueOf(currentPage));
            }
            if (StringUtil.hasLength(pageSize)){
                qo.setPageSize(Integer.valueOf(pageSize));
            }
            //调用service分页查询的方法
            PageResult<Employee> pageResult = employeeService.queryByPage(qo);
            //将查询的结果存储到请求作用域
            req.setAttribute("pageResult",pageResult);
            //转发到列表页面
            req.getRequestDispatcher("/WEB-INF/views/employee/list.jsp").forward(req,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*删除*/
    private void delete(HttpServletRequest req, HttpServletResponse resp) {
        try {
            //获取目标id
            String id = req.getParameter("id");
            //调用删除方法
            int row = employeeService.delete(Long.valueOf(id));
            //删除完毕跳转到查询
            resp.sendRedirect("/employee");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3 list.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>员工信息页面</title>
</head>
<body>
<center>
    <h3>员工列表</h3>
    <p>当前登录账号:${sessionScope.USER_IN_SESSION.username}</p>
    <p>
        <%--点击跳转到上传头像的表单页面--%>
        <a href="/headImg.jsp">
            <%--头像--%>
            <img src="/upload/${sessionScope.USER_IN_SESSION.headImg}" width="100px" height="100px">
            <p>${sessionScope.USER_IN_SESSION.headImg}</p>
        </a>
    </p>
    <p><a href="/employee?cmd=input">增加员工</a></p>
    <p><a href="/user?cmd=logout">退出登录</a></p>
    <%--分页跳转的表单--%>
    <form action="/employee" method="post">

    <table border="1px" cellpadding="0" cellspacing="0"width="800px">
        <thead>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>工资</th>
            <th>操作</th>
        </tr>
        </thead>
       <tbody>
       <%--动态展示员工列表数据--%>
       <c:forEach items="${pageResult.list}" varStatus="vs" var="employee">
           <tr class="trClass">
               <td>${vs.count}</td>
               <td>${employee.name}</td>
               <td>${employee.salary}</td>
               <td>
                   <a href="/employee?cmd=input&id=${employee.id}">修改员工信息</a>&nbsp;&nbsp;
                       <%--                    <a href="/employee?cmd=delete&id=${employee.id}">删除员工信息</a>--%>
                   <a href="#" onclick="deleteTr(${employee.id})">删除员工信息</a>
               </td>
           </tr>
       </c:forEach>
       </tbody>
        <tfoot>
          <tr align="center">
              <td colspan="9">
                  <a href="/employee?currentPage=1&pageSize=${pageResult.pageSize}">首页</a>&nbsp;&nbsp;
                  <a href="/employee?currentPage=${pageResult.prevPage}&pageSize=${pageResult.pageSize}">上一页</a>&nbsp;&nbsp;
                  <a href="/employee?currentPage=${pageResult.nextPage}&pageSize=${pageResult.pageSize}">下一页</a>&nbsp;&nbsp;
                  <a href="/employee?currentPage=${pageResult.totalPage}&pageSize=${pageResult.pageSize}">末页</a>&nbsp;&nbsp;
                  当前是第 ${pageResult.currentPage}/${pageResult.totalPage}&nbsp;&nbsp;
                  一共${pageResult.totalCount}条数据&nbsp;&nbsp;
                  跳转到第
                  <input type="text" name="currentPage" value="${pageResult.currentPage}"
                         onchange="changePagesize()" style="width: 50px">&nbsp;&nbsp;
                  每页
                    <select name="pageSize" onchange="changePagesize()">
                        <option value="3" ${pageResult.pageSize==3?'selected':''}>3</option>
                        <option value="6" ${pageResult.pageSize==6?'selected':''}>6</option>
                        <option value="9" ${pageResult.pageSize==9?'selected':''}>9</option>
                    </select>
                  条数据&nbsp;&nbsp;
              </td>
          </tr>
        </tfoot>
    </table>
    </form>
</center>

<%--鼠标移动到当前行,实现背景颜色高亮显示--%>
<script>
    //获取所有的行元素:不包含表头
    var trs = document.getElementsByClassName("trClass");
    //遍历行元素集合
    for(var i=0;i<trs.length;i++){
        //鼠标移入:当前行高亮,背景变成灰色
        trs[i].onmouseover=function (){
            this.style.backgroundColor="gray";
        }
        //鼠标移出:恢复原来背景颜色
        trs[i].onmouseout=function (){
            this.style.backgroundColor="";
        }
    }
</script>

<%--删除确认表--%>
<script>
    function deleteTr(id){
        //确认删除
       var b= window.confirm("确定要删除选中的员工信息吗?");
       if(b){//确定删除,执行后台删除操作
           window.location="/employee?cmd=delete&id="+id;
       }
    }
</script>

<%--分页表单提交函数--%>
<script>
    function changePagesize(){
        document.forms[0].submit();
    }
</script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1380918.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

day16 二叉树的最大深度 n叉树的最大深度 二叉树的最小深度 完全二叉树的节点数

题目1&#xff1a;104 二叉树的最大深度 题目链接&#xff1a;104 二叉树的最大深度 题意 二叉树的根节点是root&#xff0c;返回其最大深度&#xff08;从根节点到最远叶子节点的最长路径上的节点数&#xff09; 递归 根节点的的高度就是二叉树的最大深度 所以使用后序遍…

【Node.js学习 day4——模块化】

模块化介绍 什么是模块化与模块&#xff1f; 将一个复杂的程序文件依据一定规则&#xff08;规范&#xff09;拆分成多个文件的过程称之为模块化 其中拆分的每个文件就是一个模块&#xff0c;模块的内部数据是私有的&#xff0c;不过模块可以暴露内部数据以便其他模块使用。什…

010集:with as 代码块读写关闭文件—python基础入门实例

接009集&#xff1a; 读写文本文件的相关方法如下。 read &#xff08; size-1 &#xff09;&#xff1a;从文件中读取字符串&#xff0c; size 限制读取的字符数&#xff0c; si ze-1 指对读取的字符数没有限制。 readline &#xff08; size-1 &#xff09;&#xff1a;在…

常见的加密算法

加密算法 AES 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥&#xff0c;具体的加密流程如下图&#xff1a; RSA RSA 加密算法是一种典型的非对称加密算法&am…

JavaScript数据类型、判断、检测

JavaScript数据类型 number、string、boolean、null、undefined、symbol、bigint Object【Array、RegExp、Date、Math、Function】 存储方式 1. 基础类型存储在栈内存中&#xff0c;被引用或者拷贝时&#xff0c;会创建一个完全相同的变量。 2. 引用类型存放在堆内存中&…

[redis] redis高可用之持久化

一、Redis 高可用的相关知识 1.1 什么是高可用 在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中&#xff0c;高可用的含义似乎要宽泛一些&#xff0c;…

wpf使用Popup封装数据筛选框

(关注博主后,在“粉丝专栏”,可免费阅读此文) 类似于DevExpress控件的功能 这是DevExpress的winform筛选样式,如下: 这是DevExpress的wpf筛选样式,如下: 这是Excel的筛选样式,如下: 先看效果 本案例使用wpf原生控件封装,功能基本上都满足,只是颜色样式没有写…

轻松掌握构建工具:Webpack、Gulp、Grunt 和 Rollup 的使用技巧(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

蓝桥杯省赛无忧 STL 课件15 queue

01 queue队列 02 priority_queue优先队列 接下来介绍几种优先队列修改比较函数的方法 03 deque双端队列 04 例题讲解 https://www.lanqiao.cn/problems/1113/learning/?page1&first_category_id1&problem_id1113输入 5 IN xiaoming N IN Adel V IN laozhao N OUT …

VMware workstation搭建与安装AlmaLinux-9.2虚拟机

VMware workstation搭建与安装AlmaLinux-9.2虚拟机 适用于需要在VMware workstation平台安装AlmaLinux-9.2&#xff08;最小化安装、无图形化界面&#xff09;虚拟机。 1. 安装准备 1.1 安装平台 Windows 11 1.2. 软件信息 软件名称软件版本安装路径VMware-workstation 1…

一些硬件知识(三)

uint8_t, uint32_t, 和 uint16_t 是 C 和 C 语言中的数据类型&#xff0c;它们分别表示无符号的 8 位、32 位和 16 位整数。这些数据类型定义在标准库 <stdint.h>&#xff08;在 C 语言中&#xff09;或 <cstdint>&#xff08;在 C 中&#xff09;。 uint8_t&…

记录 | ubuntu软链接查看、删除、创建

软连接查看 ls -il 软连接删除 rm -rf ** 软连接创建 ln -s 源文件 目标文件 实例&#xff0c;软连接报错&#xff1a; 若要建立libtiny_reid.so*间软连接&#xff1a; 先删除 rm -rf libtiny_reid.so libtiny_reid.so.3 libtiny_reid.so.3.1 再建立 ln -s libtiny_re…

Nocalhost 为 KubeSphere 提供更强大的云原生开发环境

1 应用商店安装 Nocalhost Server 已集成在 KubeSphere 应用商店&#xff0c;直接访问&#xff1a; 设置应用「名称」&#xff0c;确认应用「版本」和部署「位置」&#xff0c;点击「下一步」&#xff1a; 在「应用设置」标签页&#xff0c;可手动编辑清单文件或直接点击「安装…

从DETR到Mask2former(2): 损失函数loss function

DETR的损失函数包括几个部分&#xff0c;如果只看论文或者代码&#xff0c;比较难理解&#xff0c;最好是可以打断点调试&#xff0c;对照着论文看。但是现在DETR模型都已经被集成进各种框架中&#xff0c;很难进入内部打断掉调试。与此同时&#xff0c;数据的label的前处理也比…

分享一个好用的免费在线扣图网址

具体效果 附地址 https://cutout.aiwave.cc/

MySQL 日志之二进制日志-binlog

1、简介 MySQL 的二进制日志记录了对 MySQL 所有的更改操作&#xff0c;不包括 select 和 show 等操作。二进制日志文件主要有&#xff1a;数据恢复、主从复制、审计&#xff08;判断是否有注入攻击&#xff09;等作用。 2、二进制日志参数配置 2.1、文件参数配置 linux 中 My…

STL标准库与泛型编程(侯捷)笔记2

STL标准库与泛型编程&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youbute: 侯捷-STL标准库与泛型编程 B站: 侯捷 - STL Github:STL源码剖析中源码 https://github.com/SilverMaple/STLSourceCo…

Flink窗口(2)—— Window API

目录 窗口分配器 时间窗口 计数窗口 全局窗口 窗口函数 增量聚合函数 全窗口函数&#xff08;full window functions&#xff09; 增量聚合和全窗口函数的结合使用 Window API 主要由两部分构成&#xff1a;窗口分配器&#xff08;Window Assigners&#xff09;和窗口函…

世邦spon IP网络对讲广播系统任意文件上传漏洞

产品介绍 世邦通信IP网络对讲广播系统采用领先的IPAudio™技术,将音频信号以数据包形式在局域网和广域网上进行传送,是一套纯数字传输系统。 漏洞描述 spon IP网络对讲广播系统存在任意文件上传漏洞&#xff0c;攻击者可以通过构造特殊请求包上传恶意后门文件&#xff0c;从…

软件测试|解决Github port 443 : Timed out连接超时的问题

前言 GitHub是全球最大的开源代码托管平台之一&#xff0c;许多开发者和团队使用它来管理和协作开源项目。但在当下&#xff0c;我们在clone或者提交代码时会经常遇到"GitHub Port 443: Timed Out"错误&#xff0c;这意味着我们的电脑无法建立与GitHub服务器的安全连…