• Java 分页


    1. 为什么要使用分页?

    a) 当数据量比较大的时候, 一次性查找所有数据会带来一些问题

    b) 数据库压力会比较大

    c) 数据的显示会很慢, 造成用户体验度不高

    d) 为了更方便的显示数据, 并且减小数据库的压力, 就会使用分页的技术

    2. 如何实现分页查询

    a) MySql中分页查询的实现方式

    -- limit用于分页查询, 后面有两个数字

    -- 第一个数字表示查询起始位置的索引(从0开始)

    -- 第二个数字表示每次查询数据的个数

    select * from emp limit 10,10;

    -- 必须知道当前页数(page), 每页显示的条数(size)

    -- select * from emp limit (page-1)*size,size;

    3. 分页的代码实现

    a) 定义分页实体类, 用于封装分页相关属性, 方便后续的分页实现, 代码如下(省略Getter和Setter方法)

    package com.bjsxt.pojo;

    import java.util.List;

    public class Pagination<T> {

    // 当前页数

    private int page;

    // 每页显示多少条数据

    private int size;

    // 总记录数

    private int totalCount;

    // 总页数

    private int totalPage;

    // 每次查询的起始位置

    private int start;

    // 是否有上一页

    private boolean hasPrev;

    // 上一页

    private int prevPage;

    // 是否有下一页

    private boolean hasNext;

    // 下一页

    private int nextPage;

    // 首页

    private int firstPage;

    // 尾页

    private int lastPage;

    // 分页导航块的个数

    private int navCount;

    // 导航的起始位置

    private int navBegin;

    // 导航的结束位置

    private int navEnd;

    // 查询结果对应的list集合

    private List<T> list;

    public Pagination(String page, String size, int totalCount) {

    // 当前页数

    this.page = null != page ? Integer.parseInt(page) : 1;

    // 每页显示多少条数据

    this.size = null != size ? Integer.parseInt(size) : 10;

    // 总记录数

    this.totalCount = totalCount;

    // 总页数

    this.totalPage = (int) Math.ceil(this.totalCount * 1.0 / this.size);

    // 当前页数不能大于总页数

    if(this.page > this.totalPage && this.totalPage > 0) {

    this.page = this.totalPage;

    }

    // 每次查询的起始位置

    this.start = (this.page - 1) * this.size;

    if (this.page > 1) {

    // 是否有上一页

    this.hasPrev = true;

    // 上一页

    this.prevPage = this.page - 1;

    }

    if (this.page < this.totalPage) {

    // 是否有下一页

    this.hasNext = true;

    // 下一页

    this.nextPage = this.page + 1;

    }

    // 首页

    this.firstPage = 1;

    // 尾页

    this.lastPage = this.totalPage;

    // 分页导航块的个数

    this.navCount = 10;

    // 导航的起始位置

    // if (this.page > this.totalPage - this.navCount) {

    // this.navBegin = this.totalPage - this.navCount + 1;

    // } else {

    this.navBegin = this.page - this.navCount / 2 < 1 ? 1 : this.page - this.navCount / 2;

    // }

    // 导航的结束位置

    this.navEnd = this.navBegin + this.navCount - 1 > this.totalPage ? this.totalPage

    this.navBegin + this.navCount - 1;

    }

    // 省略getter和setter方法

    }

    b) 在实体类中, 提供了一个构造器, 有三个参数, 分别为当前页page, 每页显示条数size和总记录数totalCount, 提供这三个参数, 是因为只要知道了这三个数据, 分页相关的其他数据都可以确定

    c) 分页实体类的使用, 在Servlet中接收相关参数, 封装为实体类对象, 之后调用service, service再调用dao即可, 代码如下:

    public void queryAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    String page = req.getParameter("page");

    String size = req.getParameter("size");

    int totalCount = es.queryCount();

    // 创建分页对象

    Pagination<Emp> p = new Pagination<Emp>(page, size, totalCount);

    // 调用service中的方法, 完成后查询的结果自动设置到p对象中

    es.queryAll(p);

        // 将p对象存储到作用域中, 方便jsp中使用

    req.setAttribute("p", p);

    // 请求转发

    req.getRequestDispatcher("/emplist.jsp").forward(req, resp);

    }

    @Override

    public void queryAll(Pagination<Emp> p) {

        // 调用dao

    dao.queryAll(p);

    }

    @Override

    public void queryAll(Pagination<Emp> p) {

    p.setList(query(Emp.class, "select * from emp limit ?,?", p.getStart(), p.getSize()));

    }

    d) jsp中分页的实现代码

    为您查询到 <font color="blue">${p.totalCount }</font> 条记录, 当前第 <font color="blue">${p.page }</font> 页, 共有 <font color="blue">${p.totalPage }</font> 页

    <table>

    <tr>

    <td>编号</td>

    <td>姓名</td>

    <td>薪资</td>

    <td>入职日期</td>

    <td>操作</td>

    </tr>

    <c:forEach items="${p.list }" var="e">

    <tr>

    <td>${e.empno }</td>

    <td>${e.ename }</td>

    <td>${e.sal }</td>

    <td>${e.hiredate }</td>

    <td><a href="query.sxt?op=queryByEmpno&empno=${e.empno }&page=${p.page}&size=${p.size}">修改</a> / <a href="query.sxt?op=deleteEmp&empno=${e.empno }&page=${p.page}&size=${p.size}" onclick="return confirm('确定删除吗?');">删除</a></td>

    </tr>

    </c:forEach>

    </table>

    <a href="query.sxt?op=queryAll&page=${p.firstPage }&size=${p.size}">首页</a> |

    <a href="query.sxt?op=queryAll&page=${p.prevPage }&size=${p.size}" onclick="return ${p.hasPrev?true:false}">上一页</a> |

    <c:forEach begin="${p.navBegin }" end="${p.navEnd }" var="each">

    <c:choose>

    <c:when test="${p.page==each }">

    <a href="query.sxt?op=queryAll&page=${each }&size=${p.size}"><font color="red" size="5">${each }</font></a> 

    </c:when>

    <c:otherwise>

    <a href="query.sxt?op=queryAll&page=${each }&size=${p.size}">${each }</a> 

    </c:otherwise>

    </c:choose>

    </c:forEach> |

    <a href="query.sxt?op=queryAll&page=${p.nextPage }&size=${p.size}" onclick="return ${p.hasNext?true:false}">下一页</a> |

    <a href="query.sxt?op=queryAll&page=${p.lastPage }&size=${p.size}">尾页</a>

    4. 在删除中, 分页遇到的问题

    a) 删除成功后, 如何继续停留在当前页面. 可以在删除时携带当前页数和每页显示记录数, 代码如下

    <a href="query.sxt?op=deleteEmp&empno=${e.empno }&page=${p.page}&size=${p.size}" onclick="return confirm('确定删除吗?');">删除</a>

    b) 删除最后一页的最后一条数据后, 保证回到前一页. 其实就是要求当前页数不能大于总页数, 并且总页数要大于0.

    // 当前页数不能大于总页数

    if(this.page > this.totalPage && this.totalPage > 0) {

    this.page = this.totalPage;

    }

    5. 在修改中分页问题

    a) 保证修改后留在当前页, 因为要跳转两个页面, 所以需要传值两次

    <a href="query.sxt?op=queryByEmpno&empno=${e.empno }&page=${p.page}&size=${p.size}">修改</a>

    <input type="hidden" name="page" value="${param.page }" />

    <input type="hidden" name="size" value="${param.size }" />

  • 相关阅读:
    线程基础1
    组合数学的卡特兰数 TOJ 3551: Game of Connections
    2017ACM/ICPC广西邀请赛-重现赛(感谢广西大学)
    Codeforces Round #430 (Div. 2)
    线代之高斯消元
    牛客网Wannafly模拟赛
    TOJ3039: 材质贴图
    AtCoder Grand Contest 019
    TOJ 3974: Region n条直线m个圆最多将圆分为几个区域
    AIM Tech Round 4 (Div. 2)
  • 原文地址:https://www.cnblogs.com/dudadi/p/7900431.html
Copyright © 2020-2023  润新知