|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
java比较简单,没有C++的烦琐,但学习时最好有C++为基础.与JSP和SQL起应用,功能强大.js|分页|数据|数据库 媒介
在利用数据库的过程当中,不成制止的必要利用到分页的功效,但是JDBC的标准对此却没有很好的办理。关于这个需求良多伴侣都有本人的办理计划,好比利用Vector等汇合类先保留掏出的数据再分页。但这类办法的可用性很差,与JDBC自己的接口完整分歧,对分歧范例的字段的撑持也欠好。这里供应了一种与JDBC兼容性十分好的计划。
JDBC和分页
Sun的JDBC标准的制订,偶然很让人啼笑皆非,在JDBC1.0中,关于一个了局集(ResultSet)你乃至只能实行next()操纵,而没法让其向后转动,这就间接招致在只实行一次SQL查询的情形下没法取得了局集的巨细。以是,假如你利用的是JDBC1.0的驱动,那末是几近没法完成分页的。
幸亏Sun的JDBC2标准中很好的填补了这一个不敷,增添了却果集的前后转动操纵,固然仍旧不克不及间接撑持分页,但我们已能够在这个基本上写出本人的可撑持分页的ResultSet了。
和详细数据库相干的完成办法
有一些数据库,如Mysql,Oracle等有本人的分页办法,好比Mysql可使用limit子句,Oracle可使用ROWNUM来限定了局集的巨细和肇端地位。这里以Mysql为例,其典范代码以下:
//盘算总的纪录条数
StringSQL="SELECTCount(*)AStotal"+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);
}
returnrs;
}
毫无疑问,这段代码在数据库是Mysql时将会是大度的,可是作为一个通用的类(现实上我前面要供应的就是一个通用类库中的一部分),必要顺应分歧的数据库,而基于这个类(库)的使用,也大概利用分歧的数据库,以是,我们将不利用这类办法。
另外一种烦琐的完成办法
我看过一些人的做法(现实上包含我在内,一入手下手也是利用这类办法的),即不利用任何封装,在必要分页的中央,间接操纵ResultSet滚到响应的地位,再读取响应数目的纪录。其典范代码以下:
<%
sqlStmt=sqlCon.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
java.sql.ResultSet.CONCUR_READ_ONLY);
strSQL="selectname,agefromtest";
//实行SQL语句并猎取了局集
sqlRst=sqlStmt.executeQuery(strSQL);
//猎取纪录总数
sqlRst.last();
intRowCount=sqlRst.getRow();
//记算总页数
intPageCount=(intRowCount+intPageSize-1)/intPageSize;
//调剂待显现的页码
if(intPage>intPageCount)intPage=intPageCount;
%>
<tableborder="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,接口界说以下:
publicinterfacePageableextendsjava.sql.ResultSet{
/**前往总页数
*/
intgetPageCount();
/**前往以后页的纪录条数
*/
intgetPageRowsCount();
/**前往分页巨细
*/
intgetPageSize();
/**转到指定页
*/
voidgotoPage(intpage);
/**设置分页巨细
*/
voidsetPageSize(intpageSize);
/**前往总纪录行数
*/
intgetRowsCount();
/**
*转到以后页的第一笔记录
*@exceptionjava.sql.SQLException非常申明。
*/
voidpageFirst()throwsjava.sql.SQLException;
/**
*转到以后页的最初一笔记录
*@exceptionjava.sql.SQLException非常申明。
*/
voidpageLast()throwsjava.sql.SQLException;
/**前往以后页号
*/
intgetCurPage();
}
这是一个对java.sql.ResultSet举行了扩大的接口,次要是增添了对分页的撑持,如设置分页巨细,跳转到某一页,前往总页数等等。
接着,我们必要完成这个接口,因为这个接口承继自ResultSet,而且它的年夜部分功效也都和ResultSet原有功效不异,以是这里利用了一个复杂的Decorator形式。
PageableResultSet2的类声明和成员声明以下:
publicclassPageableResultSet2implementsPageable{
protectedjava.sql.ResultSetrs=null;
protectedintrowsCount;
protectedintpageSize;
protectedintcurPage;
protectedStringcommand="";
}
能够看到,在PageableResultSet2中,包括了一个ResultSet的实例(这个实例只是完成了ResultSet接口,现实上它是由各个数据库厂商分离完成的),而且把一切由ResultSet承继来的办法都间接转发给该实例来处置。
PageableResultSet2中承继自ResultSet的次要办法:
//……
publicbooleannext()throwsSQLException{
returnrs.next();
}
//……
publicStringgetString(StringcolumnName)throwsSQLException{
try{
returnrs.getString(columnName);
}
catch(SQLExceptione){//这里是为了增添一些堕落信息的内容便于调试
thrownewSQLException(e.toString()+"columnName="
+columnName+"SQL="+this.getCommand());
}
}
//……
只要在Pageable接口中新增的办法才必要本人的写办法处置。
/**办法正文可参考Pageable.java
*/
publicintgetCurPage(){
returncurPage;
}
publicintgetPageCount(){
if(rowsCount==0)return0;
if(pageSize==0)return1;
//calculatePageCount
doubletmpD=(double)rowsCount/pageSize;
inttmpI=(int)tmpD;
if(tmpD>tmpI)tmpI++;
returntmpI;
}
publicintgetPageRowsCount(){
if(pageSize==0)returnrowsCount;
if(getRowsCount()==0)return0;
if(curPage!=getPageCount())returnpageSize;
returnrowsCount-(getPageCount()-1)*pageSize;
}
publicintgetPageSize(){
returnpageSize;
}
publicintgetRowsCount(){
returnrowsCount;
}
publicvoidgotoPage(intpage){
if(rs==null)
return;
if(page<1)
page=1;
if(page>getPageCount())
page=getPageCount();
introw=(page-1)*pageSize+1;
try{
rs.absolute(row);
curPage=page;
}
catch(java.sql.SQLExceptione){
}
}
publicvoidpageFirst()throwsjava.sql.SQLException{
introw=(curPage-1)*pageSize+1;
rs.absolute(row);
}
publicvoidpageLast()throwsjava.sql.SQLException{
introw=(curPage-1)*pageSize+getPageRowsCount();
rs.absolute(row);
}
publicvoidsetPageSize(intpageSize){
if(pageSize>=0){
this.pageSize=pageSize;
curPage=1;
}
}
//PageableResultSet2的机关办法:
publicPageableResultSet2(java.sql.ResultSetrs)throwsjava.sql.SQLException{
if(rs==null)thrownewSQLException("givenResultSetisNULL","user");
rs.last();
rowsCount=rs.getRow();
rs.beforeFirst();
this.rs=rs;
}
/*假如要进步效力,能够使用selectcount(*)语句获得一切纪录数,正文失落机关函数的rs.last();rowsCount=rs.getRow();rs.beforeFirst();三句。在挪用机关函数后挪用此办法取得一切的纪录,参数是selectcount(*)后的了局集
*/
publicvoidsetRowsCount(java.sql.ResultSetrs)throwsjava.sql.SQLException{
if(rs==null)thrownewSQLException("givenResultSetisNULL","user");
rowCount=rs.getInt(1);
}
这里只是复杂的获得一个总纪录数,并将纪录游标移回初始地位(beforefirst),同时将参数中的ResultSet赋给成员变量。
这里只是复杂的获得一个总纪录数,并将纪录游标移回初始地位(beforefirst),同时将参数中的ResultSet赋给成员变量。
Pageable的利用办法
由于Pageable接口承继自ResultSet,以是在利用办法上与ResultSet分歧,特别是在不必要分页功效的时分,能够间接当做ResultSet利用。而在必要分页时,只必要复杂的setPageSize,gotoPage,便可。
PreparedStatementpstmt=null;
Pageablers=null;
……//机关SQL,并筹办一个pstmt.
rs=newPageableResultSet2(pstmt.executeQuery());//机关一个Pageable
rs.setPageSize(20);//每页20个纪录
rs.gotoPage(2);//跳转到第2页
for(inti=0;i<rs.getPageRowsCount();i++){//轮回处置
intid=rs.getInt(“ID”);
……//持续处置
rs.next();
}
总结
一个好的基本类应当是便于利用,而且具有充足的可移植性,同时要包管其功效的完美。在下面的完成中,我们从java.sql.ResultSet接口承继出Pageable,并完成了它。这就包管了在利用中与JDBC原有操纵的分歧性,同时对原有功效没有缩减。
同时它也是易于利用的,由于封装了统统需要的操纵,以是在你的代码中独一显得"丢脸"和"不恬逸"的中央就是必要本人往机关一个PageableResultSet2。不外只需你乐意,这也是能够办理的。
固然它也有具有充实的可移植性,当你将数据库由Oracle变成Mysql大概SQLServer的时分,你仍旧可使用这些分页的代码。它在利用中(大概说在移植的过程当中)独一的限定就是你必需要利用一个撑持JDBC2的驱动(如今分明为何我把类定名为PageableResultSet2了吧。:P),不外,幸亏JDBC2已成为尺度了,尽年夜多半的数据库(如Oracle,Mysql,SQLServer)都有本人的大概第三方供应的JDBC2的驱动。
OK,这个分页的完成是不是对你的编程有匡助呢?细心看看,实在真正本人写的代码其实不多的,年夜部分都只是复杂的转发操纵。一个符合的形式使用能够帮你很年夜忙。
专门做了这个例子;而java的这个例子好像就是为了教学而写的,很多教学目的的例子是不考虑优化、性能的。 |
|