Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 768|回复: 0

JSP分页技术实现

[复制链接]

该用户从未签到

发表于 2011-10-13 14:35:52 | 显示全部楼层 |阅读模式
目前比较广泛使用的分页方式是将查询结果缓存在HttpSession或有状态bean中,翻页的时候从缓存中取出一页数据显示。这种方法有两个主要的缺点:一是用户可能看到的是过期数据;二是如果数据量非常大时第一次查询遍历结果集会耗费很长时间,并且缓存的数据也会占用大量内存,效率明显下降。
  其它常见的方法还有每次翻页都查询一次数据库,从ResultSet中只取出一页数据(使用rs.last();rs.getRow()获得总计录条数,使用rs.absolute()定位到本页起始记录)。这种方式在某些数据库(如oracle)的JDBC实现中差不多也是需要遍历所有记录,实验证明在记录数很大时速度非常慢。
  至于缓存结果集ResultSet的方法则完全是一种错误的做法。因为ResultSet在Statement或Connection关闭时也会被关闭,如果要使ResultSet有效势必长时间占用数据库连接。

  因此比较好的分页做法应该是每次翻页的时候只从数据库里检索页面大小的块区的数据。这样虽然每次翻页都需要查询数据库,但查询出的记录数很少,网络传输数据量不大,如果使用连接池更可以略过最耗时的建立数据库连接过程。而在数据库端有各种成熟的优化技术用于提高查询速度,比在应用服务器层做缓存有效多了。

  在oracle数据库中查询结果的行号使用伪列ROWNUM表示(从1开始)。例如select * from employee where rownum<10 返回前10条记录。但因为rownum是在查询之后排序之前赋值的,所以查询employee按birthday排序的第100到120条记录应该这么写:


        select * from (            select my_table.*, rownum as my_rownum from (                select name, birthday from employee order by birthday            ) my_table where rownum <120        ) where my_rownum>=100
  mySQL可以使用LIMIT子句:
    select name, birthday from employee order by birthday LIMIT 99,20
  DB2有rownumber()函数用于获取当前行数。
  SQL Server没研究过,可以参考这篇文章:http://www.csdn.net/develop/article/18/18627.shtm

  在Web程序中分页会被频繁使用,但分页的实现细节却是编程过程中比较麻烦的事情。大多分页显示的查询操作都同时需要处理复杂的多重查询条件,sql语句需要动态拼接组成,再加上分页需要的记录定位、总记录条数查询以及查询结果的遍历、封装和显示,程序会变得很复杂并且难以理解。因此需要一些工具类简化分页代码,使程序员专注于业务逻辑部分。下面是我设计的两个工具类:
  PagedStatement  封装了数据库连接、总记录数查询、分页查询、结果数据封装和关闭数据库连接等操作,并使用了PreparedStatement支持动态设置参数。
  RowSetPage  参考PetStore的page by page iterator模式, 设计RowSetPage用于封装查询结果(使用OracleCachedRowSet缓存查询出的一页数据,关于使用CachedRowSet封装数据库查询结果请参考JSP页面查询显示常用模式)以及当前页码、总记录条数、当前记录数等信息, 并且可以生成简单的HTML分页代码。
  PagedStatement 查询的结果封装成RowsetPage。

  下面是简单的使用示例:



    //DAO查询数据部分代码:
    …
    public RowSetPage getEmployee(String gender, int pageNo) throws Exception{
        String sql="select emp_id, emp_code,  user_name, real_name from employee where gender =?";
       //使用Oracle数据库的分页查询实现,每页显示5条
        PagedStatement pst =new PagedStatementOracleImpl(sql,  pageNo, 5);
        pst.setString(1, gender);
        return pst.executeQuery();
    }


    //Servlet处理查询请求部分代码:

    …
    int pageNo;
    try{
        //可以通过参数pageno获得用户选择的页码
        pageNo = Integer.parseInt(request.getParameter("pageno") );
    }catch(Exception ex){
        //默认为第一页
        pageNo=1;
    }
    String gender = request.getParameter("gender" );
    request.setAttribute("empPage", myBean.getEmployee(gender, pageNo) );
    …

    //JSP显示部分代码
<%@ page import = "page.RowSetPage"%>
    …
    <script language="javascript">
        function doQuery(){
            form1.actionType.value="doQuery";
            form1.submit();
    }
    </script>
    …
    <form name=form1 method=get>
      <input type=hidden name=actionType>
      性别:
      <input type=text name=gender size=1 value="<%=request.getParameter("gender")%>">
      <input type=button value=" 查询 " onclick="doQuery()">
<%
    RowSetPage empPage = (RowSetPage)request.getAttribute("empPage");
    if (empPage == null ) empPage = RowSetPage.EMPTY_PAGE;
%>
    …
    <table  cellspacing="0" width="90%">
        <tr> <td>ID</td> <td>代码</td> <td>用户名</td> <td>姓名</td>  </tr>
<%
    javax.sql.RowSet empRS = (javax.sql.RowSet) empPage.getRowSet();
    if (empRS!=null) while (empRS.next() ) {
%>
        <tr>   
            <td><%= empRS.getString("EMP_ID")%></td>  
            <td><%= empRS.getString("EMP_CODE")%></td>   
            <td><%= empRS.getString("USER_NAME")%></td>  
            <td><%= empRS.getString("REAL_NAME")%></td>   
        </tr>
<%
    }// end while
%>
        <tr>
<%
    //显示总页数和当前页数(pageno)以及分页代码。
    //此处doQuery为页面上提交查询动作的javascript函数名, pageno为标识当前页码的参数名
%>
            <td colspan=4><%= empPage .getHTML("doQuery", "pageno")%></td>
        </tr>
    </table>
    </form>

  效果如图:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-10 14:43 , Processed in 0.370392 second(s), 55 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表