`
zjx2388
  • 浏览: 1337025 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

很好的一个可重用分页讲解 ------ 借鉴

阅读更多

和具体数据库相关的实现方法   有一些数据库,如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”); ……//继续处理 }

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

分享到:
评论

相关推荐

    框架分页--struts-分页

    通过上述步骤,我们可以实现一个高效、简洁且可重用的Struts分页功能。这种分页方式不仅能够有效提高系统的响应速度和用户体验,还能够更好地适应不同的开发环境和技术栈。此外,这种方式也更加符合MVC的设计理念,...

    分页组件--通用的分页标签

    在JSP中,自定义标签库(Tag Library)是一种强大的工具,可以创建可重用的UI组件,例如我们的分页组件。 分页标签通常会包含以下关键元素: 1. **总记录数**:这是数据库中待分页的数据总数,用于计算总页数。 2....

    可重用的MVC分页方法(ASP.NET MVC)

    6. **扩展性与可复用性**:为了实现代码的可重用性,我们可以创建一个通用的分页帮助类或辅助方法,供多个控制器和视图共享。这样,每次需要分页功能时,只需调用这个通用方法,就能轻松实现。 综上所述,这个"可...

    可重用的分页Bean

    "可重用的分页Bean"是一个设计精良的组件,它基于经典的三层架构(表现层、业务逻辑层、数据访问层)来实现,可以方便地在JSP MVC(模型-视图-控制器)框架中复用,提高代码的可维护性和效率。在这个PageBeanDemo中...

    分页用displaytag-portlet-1.1jar包

    DisplayTag Portlet 1.1 是一个用于网页开发的开源分页库,它极大地简化了在Java Web应用程序中实现高效且美观的分页功能。这个jar包是DisplayTag项目的一个特定版本,专为portlet环境设计,portlet是Java Portal...

    C语言接口与实现--创建可重用软件的技术

    《C语言接口与实现--创建可重用软件的技术》是一本深入探讨如何通过C语言构建高效、可维护、可重用软件的专业书籍。在软件工程领域,可重用性是提高开发效率、降低维护成本的关键因素。这本书的核心目标就是教授读者...

    可重用的JAVA分页.rar

    "可重用的JAVA分页.rar"这个压缩包提供了一个简单且可复用的Java分页解决方案。 首先,我们来看`Pagination.java`,这是实现分页功能的核心类。它通常会包含如下的关键属性和方法: 1. **属性**:如总记录数...

    pager-taglib分页标签

    `pager-taglib`是一个专为JSP页面设计的分页标签库,它简化了在JSP中实现分页的过程。下面将详细介绍`pager-taglib`的安装、使用方法以及其核心知识点。 ### 1. `pager-taglib`简介 `pager-taglib`是一个开源的JSP...

    react-native-error-boundary:一个简单可重用的 React-Native 错误边界组件 :bug:

    一个简单可重用的 React-Native 组件 :bug: 安装 yarn add react-native-error-boundary 用法 该组件在其子组件树中的任何位置捕获。 不处理本机错误。 使用这个组件非常简单。 首先,您必须导入ErrorBoundary组件...

    一个用于分页的自定义标签

    总结起来,这个“一个用于分页的自定义标签”项目提供了在Java Web环境中高效、可重用的分页解决方案。通过自定义标签,开发者可以将复杂的分页逻辑封装起来,使JSP页面更加简洁,同时提高代码的可维护性和复用性。

    自定义标签小练习----一个简单的分页标签

    本篇博客“自定义标签小练习----一个简单的分页标签”将深入探讨如何实现这样一个实用功能,通过自定义标签来实现网页的分页展示。 首先,我们要理解自定义标签的工作原理。自定义标签是JSP标准标签库(JSTL)的...

    struts分页(重用).

    6. **分页组件重用**:为了实现分页的重用,你可以封装一个通用的分页组件,比如自定义的JSP标签。这个组件应该接受必要的参数(如页码、每页条数等),并负责生成分页链接和展示数据。 7. **URL参数设计**:合理...

    C语言接口与实现--创建可重用软件的技术 pdf电子版

    《C语言接口与实现--创建可重用软件的技术》是一本深入探讨如何通过C语言构建高效、可维护和可重用软件的专业书籍。该书详细阐述了C语言在设计和实现模块化接口中的核心概念和技术,旨在帮助程序员提升代码质量,...

    自定义QTableWidget实现分页。

    在QT编程中,QTableWidget是一个非常常用的控件,用于展示二维数据,但它本身并不支持内置的分页功能。在处理大量数据时,这可能会导致性能问题,因为所有的数据都会一次性加载到内存中。为了解决这个问题,我们可以...

    C语言接口与实现--创建可重用软件的技术.pdf

    C语言接口与实现--创建可重用软件的技术.pdf

    很不错的自定义分页标签

    本文将详细讲解如何实现一个很不错的自定义分页标签,以供开发者们参考和使用。 首先,我们要了解分页的基本原理。分页通常涉及到两个主要部分:前端显示和后端数据处理。前端负责展示当前页码、总页数以及翻页链接...

    C语言接口与实现-创建可重用软件的技术

    可重用性是软件工程中的一个重要概念,意味着代码可以在多个项目中重复使用,减少开发时间和成本。为了实现代码的可重用,我们需要遵循一些原则: 1. 抽象:通过封装细节,隐藏实现复杂性,只暴露必要的接口。 2. ...

Global site tag (gtag.js) - Google Analytics