首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 网络编程-> 移动开发教程
目前最好的JSP分页技术-JSP教程,Jsp/Servlet
作者:网友供稿 点击:4
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 

前言
     在使用数据库的过程中,不可避免的需要使用到分页的功能,可是jdbc的规范对此却没有很好的解决。对于这个需求很多朋友都有自己的解决方案,比如使用vector等集合类先保存取出的数据再分页。但这种方法的可用性很差,与jdbc本身的接口完全不同,对不同类型的字段的支持也不好。这里提供了一种与jdbc兼容性非常好的方案。 
 jdbc和分页
  sun的jdbc规范的制定,有时很让人哭笑不得,在jdbc1.0中,对于一个结果集(resultset)你甚至只能执行next()操作,而无法让其向后滚动,这就直接导致在只执行一次sql查询的情况下无法获得结果集的大小。所以,如果你使用的是jdbc1.0的驱动,那么是几乎无法实现分页的。
  好在sun的jdbc2规范中很好的弥补了这一个不足,增加了结果集的前后滚动操作,虽然仍然不能直接支持分页,但我们已经可以在这个基础上写出自己的可支持分页的resultset了。

 和具体数据库相关的实现方法
  有一些数据库,如mysql, oracle等有自己的分页方法,比如mysql可以使用limit子句,oracle可以使用rownum来限制结果集的大小和起始位置。这里以mysql为例,其典型代码如下:
    // 计算总的记录条数
    string sql = "select count(*) as total " + this.querypart;
    rs = db.executequery(sql);   
    if (rs.next())
    total = rs.getint(1);    
    // 设置当前页数和总页数
    tpages = (int)math.ceil((double)this.total/this.maxline);
    cpages = (int)math.floor((double)offset/this.maxline+1);
    // 根据条件判断,取出所需记录
    if (total > 0) {
      sql = query + " limit " + offset + " , " + maxline;
      rs = db.executequery(sql);      
    }   
    return rs;
  } 
  毫无疑问,这段代码在数据库是mysql时将会是漂亮的,但是作为一个通用的类(事实上我后面要提供的就是一个通用类库中的一部分),需要适应不同的数据库,而基于这个类(库)的应用,也可能使用不同的数据库,所以,我们将不使用这种方法。


 另一种繁琐的实现方法
  我看过一些人的做法(事实上包括我在内,一开始也是使用这种方法的),即不使用任何封装,在需要分页的地方,直接操作resultset滚到相应的位置,再读取相应数量的记录。其典型代码如下:
<%
sqlstmt = sqlcon.createstatement(java.sql.resultset.type_scroll_insensitive,
java.sql.resultset.concur_read_only);
strsql = "select name,age from test";
//执行sql语句并获取结果集
sqlrst = sqlstmt.executequery(strsql);
//获取记录总数
sqlrst.last();
introwcount = sqlrst.getrow();
//记算总页数
intpagecount = (introwcount+intpagesize-1) / intpagesize;
//调整待显示的页码
if(intpage>intpagecount) intpage = intpagecount;
%>
<table border="1" cellspacing="0" cellpadding="0">
<tr>
   <th>姓名</th>
   <th>年龄</th>
</tr>
<%
if(intpagecount>0){
   //将记录指针定位到待显示页的第一条记录上
   sqlrst.absolute((intpage-1) * intpagesize + 1);
   //显示数据
   i = 0;
   while(i<intpagesize && !sqlrst.isafterlast()){
      %>
<tr>
   <td><%=sqlrst.getstring(1)%></td>
   <td><%=sqlrst.getstring(2)%></td>
</tr>
      <%
      sqlrst.next();
      i++;
   }
}
%>
</table> 
  很显然,这种方法没有考虑到代码重用的问题,不仅代码数量巨大,而且在代码需要修改的情况下,将会无所适从。


 使用vector进行分页
  还见过另一些实现分页的类,是先将所有记录都select出来,然后将resultset中的数据都get出来,存入vector等集合类中,再根据所需分页的大小,页数,定位到相应的位置,读取数据。或者先使用前面提到的两种分页方法,取得所需的页面之后,再存入vector中。
  扔开代码的效率不说,单是从程序结构和使用的方便性上讲,就是很糟糕的。比如,这种做法支持的字段类型有限,int, double, string类型还比较好处理,如果碰到blob, text等类型,实现起来就很麻烦了。这是一种更不可取的方案。


 一个新的pageable接口及其实现
  很显然,看过上面三种实现方法后,我们对新的分页机制有了一个目标,即:不与具体数据库相关;尽可能做到代码重用;尽可能与原jdbc接口的使用方法保持一致;尽可能高的效率。
  首先,我们需要提供一个与java.sql.resultset向下兼容的接口,把它命名为pageable,接口定义如下:
public interface pageable extends java.sql.resultset{
/**返回总页数
*/
int getpagecount();
/**返回当前页的记录条数
*/
int getpagerowscount();
/**返回分页大小
*/
int getpagesize();
/**转到指定页
*/
void gotopage(int page) ;
/**设置分页大小
*/
void setpagesize(int pagesize);
/**返回总记录行数
*/
int getrowscount();
/**
 * 转到当前页的第一条记录
 * @exception java.sql.sqlexception 异常说明。
 */
void pagefirst() throws java.sql.sqlexception;
/**
 * 转到当前页的最后一条记录
 * @exception java.sql.sqlexception 异常说明。
 */
void pagelast() throws java.sql.sqlexception;
/**返回当前页号
*/
int getcurpage();

  这是一个对java.sql.resultset进行了扩展的接口,主要是增加了对分页的支持,如设置分页大小,跳转到某一页,返回总页数等等。
  接着,我们需要实现这个接口,由于这个接口继承自resultset,并且它的大部分功能也都和resultset原有功能相同,所以这里使用了一个简单的decorator模式。
  pageableresultset2的类声明和成员声明如下:
public class pageableresultset2 implements pageable {
    protected java.sql.resultset rs=null;
    protected int rowscount;
    protected int pagesize;
    protected int curpage;
    protected string command = "";

  可以看到,在pageableresultset2中,包含了一个resultset的实例(这个实例只是实现了resultset接口,事实上它是由各个数据库厂商分别实现的),并且把所有由resultset继承来的方法都直接转发给该实例来处理。
  pageableresultset2中继承自resultset的主要方法:
//……
public boolean next() throws sqlexception {
    return rs.next();
}
//……
public string getstring(string columnname) throws sqlexception {
    try {
        return rs.getstring(columnname);
    }
    catch (sqlexception e) {//这里是为了增加一些出错信息的内容便于调试
        throw new sqlexception (e.tostring()+" columnname="
            +columnname+" sql="+this.getcommand());
    }
}
//…… 
  只有在pageable接口中新增的方法才需要自己的写方法处理。
/**方法注释可参考pageable.java
*/
public int getcurpage() {
    return curpage;
}
public int getpagecount() {
    if(rowscount==0) return 0;
    if(pagesize==0) return 1;
    //calculate pagecount
    double tmpd=(double)rowscount/pagesize;
    int tmpi=(int)tmpd;
    if(tmpd>tmpi) tmpi++;
    return tmpi;
}
public int getpagerowscount() {
    if(pagesize==0) return rowscount;
    if(getrowscount()==0) return 0;
    if(curpage!=getpagecount()) return pagesize;
    return rowscount-(getpagecount()-1)*pagesize;
}
public int getpagesize() {
    return pagesize;
}
public int getrowscount() {
    return rowscount;
}
public void gotopage(int page) {
    if (rs == null)
        return;
    if (page < 1)
        page = 1;
    if (page > getpagecount())
        page = getpagecount();
    int row = (page - 1) * pagesize + 1;
    try {
        rs.absolute(row);
        curpage = page;
    }
    catch (java.sql.sqlexception e) {
    }
}
public void pagefirst() throws java.sql.sqlexception {
    int row=(curpage-1)*pagesize+1;
    rs.absolute(row);
}
public void pagelast() throws java.sql.sqlexception {
    int row=(curpage-1)*pagesize+getpagerowscount();
    rs.absolute(row);
}
public void setpagesize(int pagesize) {
    if(pagesize>=0){
        this.pagesize=pagesize;
        curpage=1;
    }

  pageableresultset2的构造方法:
public pageableresultset2(java.sql.resultset rs) throws java.sql.sqlexception {
    if(rs==null) throw new sqlexception("given resultset is null","user");
   
    rs.last();
    rowscount=rs.getrow();
    rs.beforefirst();
   
    this.rs=rs;

  这里只是简单的取得一个总记录数,并将记录游标移回初始位置(before first),同时将参数中的resultset赋给成员变量。


 pageable的使用方法
  因为pageable接口继承自resultset,所以在使用方法上与resultset一致,尤其是在不需要分页功能的时候,可以直接当成resultset使用。而在需要分页时,只需要简单的setpagesize, gotopage,即可。
preparedstatement pstmt=null;
pageable rs=null;
……//构造sql,并准备一个pstmt.
rs=new pageableresultset2(pstmt.executequery());//构造一个pageable
rs.setpagesize(20);//每页20个记录
rs.gotopage(2);//跳转到第2页
for(int i=0; i<rs.getpagerowscount(); i++){//循环处理
int id=rs.getint(“id”);
……//继续处理

rs.next();


 总结
  一个好的基础类应该是便于使用,并且具备足够的可移植性,同时要保证其功能的完善。在上面的实现中,我们从java.sql.resultset接口继承出pageable,并实现了它。这就保证了在使用中与jdbc原有操作的一致性,同时对原有功能没有缩减。
  同时它也是易于使用的,因为封装了一切必要的操作,所以在你的代码中唯一显得"难看"和"不舒服"的地方就是需要自己去构造一个pageableresultset2。不过只要你愿意,这也是可以解决的。
  当然它也有具有充分的可移植性,当你将数据库由oracle变为mysql或者sqlserver的时候,你仍然可以使用这些分页的代码。它在使用中(或者说在移植的过程中)唯一的限制就是你必须要使用一个支持jdbc2的驱动(现在明白为什么我把类命名为pageableresultset2了吧。:p),不过,好在jdbc2已经成为标准了,绝大多数的数据库(如oracle, mysql, sqlserver)都有自己的或者第三方提供的jdbc2的驱动。
  ok,这个分页的实现是否对你的编程有帮助呢?仔细看看,其实真正自己写的代码并不多的,大部分都只是简单的转发操作。一个合适的模式应用可以帮你很大忙。


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·ems图片格式转换(java)程序
·使用hashtable实现的购物车-ASP教程,ASP应用
·Java中数据库事务处理的实现-JSP教程,Java技巧及代码
·Oracle数据库操作类(c#)-.NET教程,C#语言
·移动短消息技术演进与业务发展浅析
·ASP生成静态网页,学习CASE的用法,以及“权限”的一种控制方法-ASP教程,组件开发
·中国电信发展移动通信的制式与频段选择
·ASP中access数据库的路径问题-ASP教程,数据库相关
·td-scdma系统移动台接入过程浅析
·JAVA与数据库连接方法(三)-JSP教程,数据库相关
最新文章
·fireworks表现vista毛玻璃朦胧效果_fireworks教程
·google adsense哪些情况会被k号_网赚技巧
·减少google adsense展示单元并不能提高收入_网赚技巧
·google adsense“允许域名”新功能很有用_网赚技巧
·于源:办南京人“淘宝”的大三学生_站长访谈
·谈谈网站策划和网站运营方面的点滴经验_站长心得
·美国网站兵败中国的10大思路性执行错误_站长心得
·付款流程中的电话确认_google推广
·google adsense的部分规则的背面_google推广
·googleadsense富翁排行榜最猛每月赚30万美元_google推广
相关主题
  • 目前最好的JSP分页技术-JSP教程,Jsp/Servlet
  • 目前最好的JSP分页技术-JSP教程,Jsp/Servlet
  • 西部数码虚拟主机

    友情链接
    CNNIC 西部数码
    万网 自助建站
    虚拟主机 asp空间
    域名注册 域名
    域名申请 主页空间
    论坛空间 网站空间
    国际域名 虚拟空间
    空间租用 DDOS防火墙
    成都主机托管 四川主机托管
    主机租用 服务器租用
    网站目录 自助建站
    虚拟主机 网址大全
    软件下载
    自助链接
    虚拟主机资讯 特价虚拟主机
    版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
    关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
    特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
    发表评论 打印  刷新     关闭