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}">首页 上一页 </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}">下一页 尾页 </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>
