从零开始学JDBC--1.21 分页技术

分页技术:

  
  如果数据有1000条,分页进行显示,每页显示10条,共100页;
  分页的好处在于: 利于页面布局,且显示的效率高!

分页关键点:
1. 分页SQL语句;
2. 后台处理逻辑的实现: dao/service/servlet/JSP

分页技术实现的原理:

  为了实现数据共享,我们使用PageBean来对分页相关的信息进行封装。
  其中,PageBean中封装的内容主要有:
   【 当前页,每页显示的行数,总记录数,总页数,查询到的该页数据(用List进行封装)】

  这样,在JSP层,从前台向后台请求的数据:当前页码;
  
  在Servlet层获取请求参数,创建PageBean对象,封装当前页码到PageBean对象中;创建Service实例对象并调用其分页查询的方法:getAll(PageBean bean),将PageBean的引用作为参数传递给Service层。
  
  在Service层,创建Dao实例,并调用其分页方法getAll(PageBean bean),同样将PageBean作为参数传递给Dao层
  
  在Dao层,这里主要有两个重要的方法,第一是获取总记录数getTotalCount(),第二是获取当前分页对应的数据信息getAll(PageBean)
  

实现步骤:

0. 环境准备

 a) 引入jar文件及引入配置文件
  i. 数据库驱动包
  ii. C3P0连接池: jar文件 及 配置文件
  iii. DbUtis组件: 使用DbUtils组件,可以将连接管理交给DataSource来管理,就可以省略获取连接的过程

 b) 公用类的设计: JdbcUtils.java

package cn.itcast.utils;

import javax.sql.DataSource;
import org.apache.commons.dbutils.QueryRunner;
import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * 工具类
 * 1. 初始化C3P0连接池
 * 2. 创建DbUtils核心工具类对象
 *
 */
public class JdbcUtils {

    /**
     *  1. 初始化C3P0连接池
     */
    private static  DataSource dataSource;
    static {
        dataSource = new ComboPooledDataSource();
    }

    /**
     * 2. 创建DbUtils核心工具类对象
     */
    public static QueryRunner getQueryRuner(){
        // 创建QueryRunner对象,传入连接池对象
        // 在创建QueryRunner对象的时候,如果传入了数据源对象;
        // 那么在使用QueryRunner对象方法的时候,就不需要传入连接对象;
        // 会自动从数据源中获取连接(不用关闭连接)
        return new QueryRunner(dataSource);
    }
}

1. 先设计:PageBean.java

PageBean用来保存分页调用过程中必要的参数:

    private int currentPage = 1;      // 当前页, 默认显示第一页
    private int lineCountPerPage = 4; // 每页显示的行数(查询返回的行数), 默认每页显示4行
    private int totalCount;           // 总记录数
    private int totalPage;            // 总页数 = 总记录数 / 每页显示的行数 (+ 1)
    private List<T> pageData;         // 分页查询到的数据

    getters & setters

2. Dao接口设计/实现: 2个方法

2.1 统计总记录数

public int getTotalCount()

2.2 dao层中分页查询的逻辑

public void getAll(PageBean<Employee> pb);

a. 获取记录总数
b. 计算当前页的起始行、返回的行数

SELECT * FROM employee LIMIT 0,4   --查询第一页

SELECT * FROM employee LIMIT 4,4   --第二页

SELECT * FROM employee LIMIT 8,4   --第三页

SELECT * FROM employee LIMIT 12,4  --第四页

从以上的查询规律中我们可以总结出起始页的计算方式:
(当前页-1)* 每页显示行数

int currentPage = pb.getCurrentPage();                      //首次访问,默认当前页是0,其他情况根据参数传递
int index = (currentPage - 1) * pb.getLineCountPerPage();   // 计算查询的起始行
int count = pb.getLineCountPerPage();                       //获取返回行数

c. 分页差询sql执行

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

QueryRunner qr = JdbcUtils.getQueryRuner();
List<Employee> pageData = qr.query(sql, new BeanListHandler<Employee>(Employee.class), index,count);
pb.setPageData(pageData);   //到这里,数据已经通过PageBean的引用设置进去了,在servlet端只需取出来就行

bug: 当前jsp页面是首页,再点击上一页 报错,
   当前页面是末页,再点击下一页时显示不对!
解决:在步骤a、b之间增加判断:

  1. 如果请求的当前页 <= 0 ,将当前页设置为1,即查询首页
  2. 如果当前页 > 最大页数 , 将当前页设置为最大页数

3. Service/Servlet

service中只是创建并调用Dao,没有复杂逻辑

我们看看Servlet中的代码:

String uri = "" ;
try {
    //1. 从参数中获取“当前页”参数 
    String currentPage = (String)request.getParameter("currentPage");
    //判断: 第一次访问时,参数是null,应默认给其赋值为“1”
    if(currentPage ==null || "".equals(currentPage.trim())){
        currentPage = "1";
    }
    //格式转换
    int currentPageNum = Integer.parseInt(currentPage);

    //2. 创建PageBean对象,设置当前页的参数进去
    PageBean<Employee> pageBean = new PageBean<Employee>();
    pageBean.setCurrentPage(currentPageNum);

    //3. 调用Service
    service.getAll(pageBean);   //通过底层方法进行数据填充

    //4. 保存pageBean 对象,到request域中
    request.setAttribute("pageBean", pageBean);

    //5. 跳转
    uri = "/WEB-INF/list.jsp";
} catch (Exception e) {
    // 如果出错,则跳转到错误页面,进行友好提示
    uri = "/error/error.jsp";
}
request.getRequestDispatcher(uri).forward(request, response);

4. JSP页面的处理逻辑

 <table border="1" width="80%" align="center" cellpadding="5" cellspacing="0">
    <tr> 
        <td>序号</td> 
        <td>员工编号</td> 
        <td>员工姓名</td> 
    </tr>
    <c:choose>
    <c:when test="${not empty requestScope.pageBean.pageData}">
        <c:forEach var="emp" items="${requestScope.pageBean.pageData }" varStatus="vs">
            <tr>
                <td>${vs.count }</td>
                <td>${emp.empId }</td>
                <td>${emp.empName }</td>
            </tr>
        </c:forEach>
    </c:when>
    <c:otherwise>
        <tr>
            <td colspan="3">对不起,没有你要找的数据</td>
        </tr>
    </c:otherwise>
    </c:choose>

    <tr>
            <td colspan="3" align="center">
                当前${requestScope.pageBean.currentPage }/${requestScope.pageBean.totalPage }页     &nbsp;&nbsp;

                <a href="${pageContext.request.contextPath }/IndexServlet?currentPage=1">首页</a>
                <a href="${pageContext.request.contextPath }/IndexServlet?currentPage=${requestScope.pageBean.currentPage-1}">上一页 </a>
                <a href="${pageContext.request.contextPath }/IndexServlet?currentPage=${requestScope.pageBean.currentPage+1}">下一页 </a>
                <a href="${pageContext.request.contextPath }/IndexServlet?currentPage=${requestScope.pageBean.totalPage}">末页</a>
            </td>
        </tr>
  </table>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值