Skip to content

17 分页实现

分页查询是Java Web开发之中十分常用的技术。在数据库量非常大的情况下,不适合将所有数据显示到一个页面之中,既给查看带来有便,又占用了程序及数据库的资源,此时就需要对数据进行分页查询。 通过JDBC实现分页查询的方法有很多种,而且不同的数据库机制也提供了不同的分页方式,在这里介绍两种非常典型的分页方法。

1、通过ResultSet的光标实现分页 ResultSet是JDBC API中封装的查询结果集对象,通过该对象可以实现数据的分页显示,优点是在各种数据库上通用,缺点是占用大量资源,不适合数据量大的情况。

2、通过数据库机制进行分页 很多数据库自身都提供了分页机制,如MySQL的limit关键字,SQLServer的top关键字,oracle的ROWNUM的特性等,都可以设置数据返回的记录数,通过数据库提供的分页机制实现分页查询,其优点是减少数据库资源的开销提升程序的性能,缺点是只针对一种数据库通用。 由于通用ResultSet的光标实现数据分页存在性能方面的缺陷,所以在实际开发中大多都是采用数据库的分页机制来实现分页查询。

17.1 创建数据库

sql
CREATE DATABASE /*!32312 IF NOT EXISTS*/`his1215` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `his1215`;

/*Table structure for table `disease` */

DROP TABLE IF EXISTS `disease`;

CREATE TABLE `disease` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `disease_code` varchar(100) NOT NULL COMMENT '疾病助记编码',
  `disease_name` varchar(100) DEFAULT NULL COMMENT '疾病名称',
  `disease_icd` varchar(100) NOT NULL COMMENT '国际ICD编码',
  `cate_id` int(11) DEFAULT NULL COMMENT '主键',
  `createtime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `valid` varchar(5) DEFAULT '1' COMMENT '是否有效,默认1 有效,0无效',
  PRIMARY KEY (`id`),
  KEY `FK_Reference_1` (`cate_id`),
  CONSTRAINT `FK_Reference_1` FOREIGN KEY (`cate_id`) REFERENCES `dise_category` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COMMENT='疾病信息';

/*Data for the table `disease` */

insert  into `disease`(`id`,`disease_code`,`disease_name`,`disease_icd`,`cate_id`,`createtime`,`valid`) values (2,'GDXHL0','古典型霍乱0','A00.0510',1,'2020-12-16 08:41:28','1'),(3,'GDXHL1','古典型霍乱1','A00.0511',1,'2020-12-16 08:41:28','1'),(4,'GDXHL2','古典型霍乱2','A00.0512',1,'2020-12-16 08:41:28','1'),(5,'GDXHL3','古典型霍乱3','A00.0513',1,'2020-12-16 08:41:28','1'),(6,'GDXHL4','古典型霍乱4','A00.0514',1,'2020-12-16 08:41:28','1'),(7,'GDXHL5','古典型霍乱5','A00.0515',1,'2020-12-16 08:41:28','1'),(8,'GDXHL6','古典型霍乱6','A00.0516',1,'2020-12-16 08:41:28','1'),(9,'GDXHL7','古典型霍乱7','A00.0517',1,'2020-12-16 08:41:28','1'),(10,'GDXHL8','古典型霍乱8','A00.0518',1,'2020-12-16 08:41:28','1'),(14,'GDXHL2','古典型霍乱2','A00.0512',1,'2020-12-16 09:06:13','1'),(15,'GDXHL3','古典型霍乱3','A00.0513',1,'2020-12-16 09:06:13','1'),(23,'GDXHL1','xx疾病','A510.11',1,'2020-12-16 13:41:58','1');

17.2 创建项目

g: com.neuedu

a: Java1Fenye

v: 1.0

17.3 添加依赖

  • lombok
  • jstl
  • jsp
  • servlet
  • jdbcutil
  • junit
<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>



    <!--单元测试-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <!--Servlet-API 编译时需要-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>

    <!--JSP-API 编译时需要-->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>


    <!-- lombok 帮助快速生成 setter、getter toString equals、hashcode 构造器 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.12</version>
      <scope>provided</scope>
    </dependency>

    <!--jstl Apache 的标准标签库-->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

    <dependency>
      <groupId>com.neuedu</groupId>
      <artifactId>jdbcutil</artifactId>
      <version>1.0</version>
    </dependency>
    
  </dependencies>

17.4 连接数据库的配置文件 jdbc.properties

properties
jdbc.url=jdbc:mysql://127.0.0.1:3306/his1215?characterEncoding=utf8&useUnicode=true&useSSL=false
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root

17.5 实体类Disease

java
package com.neuedu.entity;

import com.neuedu.util.Column;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;


/**
 * 项目:      Java1Fenye
 * 类名:       Disease
 * 创建时间:  2020/12/20  9:08
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Disease {

    private Integer id;


    @Column("disease_code")
    private String diseaseCode;

    @Column("disease_name")
    private String diseaseName;

    @Column("disease_icd")
    private String diseaseIcd;

    @Column("cate_id")
    private Integer cateId;

    private Date createtime;
    private String valid;

}

17.6 数据访问对象DiseaseDao

java
package com.neuedu.dao;

/**
 * 项目:      Java1Fenye
 * 类名:       DiseaseDao
 * 创建时间:  2020/12/20  9:10
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */

import com.neuedu.entity.Disease;
import com.neuedu.util.JDBCUtil;

import java.util.List;

/**
 * 项目:      his1215
 * 类名:       DiseaseDaoImpl
 * 创建时间:  2020/12/15  10:41
 * 描述 :     DiseaseDaoImpl 实现
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class DiseaseDao  {
    
    public List<Disease> selectList(String sql, Object... args) {
        return JDBCUtil.executeQuery(sql, Disease.class, args);
    }

    
    public Disease selectById(Integer id) {
        String sql = " select * from disease where id = ?";
        return JDBCUtil.getOne(sql, Disease.class, id);
    }

    
    public boolean update(Disease disease) {
        String sql = " UPDATE   disease SET disease_code = ? ,   disease_name = ?  ,   disease_icd = ? ,   cate_id = ?  ,   valid = ?     WHERE id = ?  ";
        return JDBCUtil.executeUpdate(sql,
                disease.getDiseaseCode(),
                disease.getDiseaseName(),
                disease.getDiseaseIcd(),
                disease.getCateId(),
                disease.getValid(),
                disease.getId()
        );
    }

    
    public boolean deleteById(Integer id) {
        String sql = " delete from disease where id = ?";
        return JDBCUtil.executeUpdate(sql,id);
    }

    
    public boolean batchDel(String sql, Object... parm) {
        return JDBCUtil.executeUpdate(sql,parm );
    }

    
    public boolean insert(Disease disease) {
        String sql = " INSERT INTO disease(  disease_code, disease_name,  disease_icd , cate_id)  values  (?,?,?,?) ";
        return JDBCUtil.executeUpdate(sql,
                disease.getDiseaseCode(),
                disease.getDiseaseName(),
                disease.getDiseaseIcd(),
                disease.getCateId()
        );
    }

    
    public long selectCount(String sql, Object... args) {
        return JDBCUtil.executeQueryCount(sql,args);
    }

}

17.7 业务层DiseaseService

java
package com.neuedu.service;

import com.neuedu.dao.DiseaseDao;
import com.neuedu.entity.Disease;


import java.util.List;

/**
 * 项目:      his1215
 * 类名:       DiseaseServiceImpl
 * 创建时间:  2020/12/15  14:27
 * 描述 :     查询
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class DiseaseService {

    private DiseaseDao diseaseDao = new DiseaseDao();

    /**
     * 查询集合,不分页
     * @return
     */
  
    public List<Disease> queryList() {
        String sql = " select * from disease ";
        List<Disease> list =  diseaseDao.selectList(sql);
        return list;
    }

    /**
     * 查询集合,分页
     * @return
     */
  
    public List<Disease> queryListByPage(Integer pageNo,Integer pageCount) {

        String sql = " select * from disease  limit ?  , ?  ";

        int start = (pageNo-1) * pageCount ;
        List<Disease> list =  diseaseDao.selectList(sql,start,pageCount);


        return list;

    }

  
    public Disease queryById(Integer id) {
        return diseaseDao.selectById(id);
    }

  
    public boolean edit(Disease disease) {
        return diseaseDao.update(disease);
    }

  
    public boolean deleteById(Integer id) {
        return diseaseDao.deleteById(id);
    }

  
    public boolean save(Disease disease) {
        return diseaseDao.insert(disease);
    }

  
    public boolean batchdel(String[] ids) throws Exception {

        //物理删除 , delete  from  disease where id i ???????


        if(ids == null){
            throw new Exception("批量删除 id 不能为空");
        }
        StringBuffer sql = new StringBuffer(" delete  from  disease where id in (  ");

        for (String id : ids) {
            sql.append("?,");
        }

        //移除最后的 ,
        sql.deleteCharAt(sql.length()-1);

        sql.append(" ) ");
        //逻辑删除  update disease set valid = 0 where id  = ?????

        System.out.println("sql: "+sql.toString());

        return diseaseDao.batchDel(sql.toString(),ids);

    }
}

17.8 控制层DiseaseController

java
package com.neuedu.controller;

import com.neuedu.entity.Disease;
import com.neuedu.service.DiseaseService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 项目:      Java1Fenye
 * 类名:       DiseaseController
 * 创建时间:  2020/12/20  9:26
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 *
 * http://127.0.0.2:8080/web/disease
 */
@WebServlet( name = "DiseaseController",urlPatterns = "/disease")
public class DiseaseController extends HttpServlet {

    DiseaseService diseaseService = new DiseaseService();


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        List<Disease> list = diseaseService.queryList();

        req.setAttribute("list",list);
        req.getRequestDispatcher("/WEB-INF/disease/disease_list.jsp").forward(req,resp);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

17.9 列表页disease_list.jsp

实现查询方法

html
<%--
  Created by IntelliJ IDEA.
  User: root
  Date: 2020/12/20
  Time: 9:29
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>


<table border='1' width='100%' cellpadding='0' cellspacing='0'>
    <tr>
        <td><input type="checkbox" /></td>
        <td>序号</td>
        <td>diseaseCode</td>
        <td>diseaseName</td>
        <td>diseaseIcd</td>
        <td>cateId</td>
        <td>createtime</td>
        <td>valid</td>
        <td>操作</td>
    </tr>


    <c:forEach var="disease" items="${list}" varStatus="stat"  >
        <tr>
            <td><input type="checkbox" name="ids" value="${disease.id}" /></td>
            <td>${stat.count}</td>
            <td>${disease.diseaseCode}</td>
            <td>${disease.diseaseName}</td>
            <td>${disease.diseaseIcd}</td>
            <td>${disease.cateId}</td>
            <td>${disease.createtime}</td>
            <td>${disease.valid}</td>

            <td><a href='disease?type=toEdit&id=${disease.id}'>编辑</a> <a href='disease?type=del&id=${disease.id}'>删除</a></td>
        </tr>
    </c:forEach>

</table>


</body>
</html>

17.10 解决el表达式默认不解析的问题

需要把Servlet的版本改成2.5+

xml
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
  <display-name>Archetype Created Web Application</display-name>
</web-app>

17.10分页的过程

17.10.1 封装分页信息

java
package com.neuedu.framework;

import java.util.List;

/**
 * 项目:      Java1Fenye
 * 类名:       PageInfo
 * 创建时间:  2020/12/20  9:56
 * 描述 :     分页信息封装
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class PageInfo {


    private Integer pageNo = 1; //查询第几页
    private Integer pageSize = 10; //每页显示条数


    private Integer totalPage ;//总页数
    private Integer totalCount;// 总条数


    private List list;   //查询的数据


    public Integer getPageNo() {
        return pageNo;
    }

    public void setPageNo(Integer pageNo) {
        this.pageNo = pageNo;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public Integer getTotalPage() {

        return totalCount%pageSize==0?totalCount/pageSize  :  (totalCount/pageSize)+1;
    }

    public void setTotalPage(Integer totalPage) {
        this.totalPage = totalPage;
    }

    public Integer getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(Integer totalCount) {
        this.totalCount = totalCount;
    }

    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }



    public static PageInfo getPageInfo(){
        return new PageInfo();
    }


}

17.10.2 在service层添加分页查询的方法

java
 package com.neuedu.service;

import com.neuedu.dao.DiseaseDao;
import com.neuedu.entity.Disease;
import com.neuedu.framework.PageInfo;


import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.List;

/**
 * 项目:      his1215
 * 类名:       DiseaseServiceImpl
 * 创建时间:  2020/12/15  14:27
 * 描述 :     查询
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class DiseaseService {

    private DiseaseDao diseaseDao = new DiseaseDao();

    /**
     * 查询集合,不分页
     * @return
     */
  
    public List<Disease> queryList() {
        String sql = " select * from disease ";
        List<Disease> list =  diseaseDao.selectList(sql);
        return list;
    }

    /**
     * 查询集合,分页
     * @return
     */
  
    public PageInfo queryListByPage( HttpServletRequest request) throws UnsupportedEncodingException {

        request.setCharacterEncoding("utf-8");

        PageInfo pageInfo = PageInfo.getPageInfo();

        if(request.getParameter("pageNo") != null && !"".equals(request.getParameter("pageNo"))){
            int pageNo = Integer.parseInt(request.getParameter("pageNo"));
            pageInfo.setPageNo(pageNo);
        }


        if(request.getParameter("pageSize") != null && !"".equals(request.getParameter("pageSize"))){
            int pageSize = Integer.parseInt(request.getParameter("pageSize"));
            pageInfo.setPageSize(pageSize);
        }


        String diseaseName = request.getParameter("diseaseName");

        if(diseaseName==null){
            diseaseName = "";
        }

        diseaseName = "%"+diseaseName.trim()+"%";

        String sql = " select * from disease where disease_name like ?   limit ?  , ?  ";

        int start = (pageInfo.getPageNo()-1) * pageInfo.getPageSize() ;
        List<Disease> list =  diseaseDao.selectList(sql,diseaseName,start,pageInfo.getPageSize());


        String sql2 = "  select count(1) from disease   where disease_name like ?  ";
        long count =  diseaseDao.selectCount(sql2,diseaseName);



        pageInfo.setList(list);
        pageInfo.setTotalCount((int) count);

        return pageInfo;

    }

  
    public Disease queryById(Integer id) {
        return diseaseDao.selectById(id);
    }

  
    public boolean edit(Disease disease) {
        return diseaseDao.update(disease);
    }

  
    public boolean deleteById(Integer id) {
        return diseaseDao.deleteById(id);
    }

  
    public boolean save(Disease disease) {
        return diseaseDao.insert(disease);
    }

  
    public boolean batchdel(String[] ids) throws Exception {

        //物理删除 , delete  from  disease where id i ???????


        if(ids == null){
            throw new Exception("批量删除 id 不能为空");
        }
        StringBuffer sql = new StringBuffer(" delete  from  disease where id in (  ");

        for (String id : ids) {
            sql.append("?,");
        }

        //移除最后的 ,
        sql.deleteCharAt(sql.length()-1);

        sql.append(" ) ");
        //逻辑删除  update disease set valid = 0 where id  = ?????

        System.out.println("sql: "+sql.toString());

        return diseaseDao.batchDel(sql.toString(),ids);

    }
}

测试类

java
package com.neuedu.service;

import com.neuedu.entity.Disease;
import com.neuedu.framework.PageInfo;
import org.junit.Test;

import java.util.List;

import static org.junit.Assert.*;

/**
 * 项目:      Java1Fenye
 * 类名:       DiseaseServiceTest
 * 创建时间:  2020/12/20  9:15
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 */
public class DiseaseServiceTest {

    DiseaseService service = new DiseaseService();
    @Test
    public void queryList() {
        System.out.println(service.queryList());
    }

    @Test
    public void queryListByPage() {
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPageNo(3);
        pageInfo.setPageSize(50);

        pageInfo  = service.queryListByPage(pageInfo);


        System.out.println("当前页号:"+pageInfo.getPageNo());
        System.out.println("每页显示条数:"+pageInfo.getPageSize());
        System.out.println("总条数:"+pageInfo.getTotalCount());
        System.out.println("总页数:"+pageInfo.getTotalPage());

        for (Object o : pageInfo.getList()) {
            System.out.println(o);
        }
    }
}

17.10.3 控制器代码修改

java
package com.neuedu.controller;

import com.neuedu.entity.Disease;
import com.neuedu.framework.PageInfo;
import com.neuedu.service.DiseaseService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * 项目:      Java1Fenye
 * 类名:       DiseaseController
 * 创建时间:  2020/12/20  9:26
 * 描述 :
 * 作者 :     张金山
 * QQ :     314649444
 * Site:      https://jshand.gitee.io
 *
 * http://127.0.0.2:8080/web/disease
 */
@WebServlet( name = "DiseaseController",urlPatterns = "/disease")
public class DiseaseController extends HttpServlet {

    DiseaseService diseaseService = new DiseaseService();


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//        List<Disease> list = diseaseService.queryList();
        PageInfo pageInfo = diseaseService.queryListByPage(req);

        req.setAttribute("pageInfo",pageInfo);
        req.getRequestDispatcher("/WEB-INF/disease/disease_list.jsp").forward(req,resp);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

17.10.4 列表页面jsp

html
<%--
  Created by IntelliJ IDEA.
  User: root
  Date: 2020/12/20
  Time: 9:29
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <script>
        function query(pageNo) {

            document.getElementById("pageNo").value = pageNo;
            document.forms[0].submit();

        }
    </script>
</head>
<body>

<form method="post" action="${pageContext.request.contextPath}/disease">
    <input id="pageNo" type="hidden" name="pageNo" value="${pageInfo.pageNo}"/>
    <input id="pageSize" type="hidden" name="pageSize" value="${pageInfo.pageSize}"/>


    <label>疾病名称</label>
    <input type="text" name="diseaseName" value="${param['diseaseName']}" />

    <input type="submit">


</form>


<table border='1' width='100%' cellpadding='0' cellspacing='0'>
    <tr>
        <td><input type="checkbox"/></td>
        <td>序号</td>
        <td>diseaseCode</td>
        <td>diseaseName</td>
        <td>diseaseIcd</td>
        <td>cateId</td>
        <td>createtime</td>
        <td>valid</td>
        <td>操作</td>
    </tr>

    <c:forEach var="disease" items="${pageInfo.list}" varStatus="stat">
        <tr>
            <td><input type="checkbox" name="ids" value="${disease.id}"/></td>
            <td>${stat.count}</td>
            <td>${disease.diseaseCode}</td>
            <td>${disease.diseaseName}</td>
            <td>${disease.diseaseIcd}</td>
            <td>${disease.cateId}</td>
            <td>${disease.createtime}</td>
            <td>${disease.valid}</td>

            <td><a href='disease?type=toEdit&id=${disease.id}'>编辑</a> <a href='disease?type=del&id=${disease.id}'>删除</a>
            </td>
        </tr>
    </c:forEach>

</table>

<p>
    当前页号:${pageInfo.pageNo}/${pageInfo.totalPage}

    <c:if test="${pageInfo.pageNo == 1}">首页&nbsp;&nbsp;上一页 </c:if>

    <c:if test="${pageInfo.pageNo > 1}">

        <a href="javascript:query(1)">首页</a>
        <a href="javascript:query(${pageInfo.pageNo -1 })">上一页</a>
    </c:if>



    <c:if test="${pageInfo.pageNo == pageInfo.totalPage}">下一页&nbsp;&nbsp;尾页 </c:if>

    <c:if test="${pageInfo.pageNo < pageInfo.totalPage}">

        <a href="javascript:query(${pageInfo.pageNo + 1 })">下一页</a>
        <a href="javascript:query(${pageInfo.totalPage })">尾页</a>
    </c:if>


</p>


</body>
</html>

Released under the MIT License.