- 浏览: 1336988 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
kay11:
...
JAVA生成简单的随机字符串(a-zA-Z0-9) -
zhangliguoaccp:
您好关于登录页面的验验证码这块怎么解决的?还有登录成功后,跳转 ...
JAVA,模拟HTTP登录 -
107x:
不错,谢谢!
<c:foreach 循环 map -
wenjin:
不知楼主是不还在想请叫一下我自己开的Tomcat下载一个文件C ...
Android 下载文件及写入SD卡 -
zyywgf:
JSTL c标签,fn标签,fmt标签
和具体数据库相关的实现方法 有一些数据库,如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,这个分页的实现是否对你的编程有帮助呢?仔细看看,其实真正自己写的代码并不多的,大部分都只是简单的转发操作。一个合适的模式应用可以帮你很大忙。
发表评论
-
oracle 按每天、周、月、季度、年统计
2018-07-30 09:27 1770//按天统计,createtime为数据库的date类型,格 ... -
oracle case when 复杂统计SQL
2015-10-21 10:18 2873select substr(unitcode,0,6),c ... -
oracle 取树形结构的数据,一条sql
2013-05-16 15:47 1877例子:select * from tb_cod_ ... -
SQL中in和exists的区别
2013-03-12 11:53 1501in和existsin 是把外表和内表作hash 连接,而e ... -
A表字段更新为B表的字段值
2013-03-12 11:34 2185T1表 结构 id name sc ... -
db2 备份表的sql
2013-03-07 18:09 16571)创建一个备份表create table t_public ... -
sql 添加修改删除字段 语句
2013-02-26 10:32 8981.增加字段 alter table docdsp ... -
Oracle一列的多行数据拼成一行显示字符
2013-01-23 11:16 8476Oracle一列的多行数据拼成一行显示字符 oracle ... -
从 char 数据类型到 datetime 数据类型的转换导致 datetime 值越界。
2012-12-05 14:28 1443com.microsoft.sqlserver.jdbc.SQ ... -
db2采用移除而非删除,补救彻底删除数据库方法
2012-11-07 15:51 1499db2采用自带的客户端,删除数据库不小心点了 “移除”而非“删 ... -
DB2错误信息 查看命令
2012-11-07 15:49 975本机如果安装了DB2数据库,可以直接使用命令查看错误代码对应的 ... -
DB2错误信息(按sqlcode排序)
2012-10-22 13:21 11039DB2错误信息(按sqlcode排序) sqlcode sq ... -
数据库取表的前n条记录
2012-08-17 16:22 1462关于row_number() over()的用法 介绍 ... -
DB2 TOP N问题解决方法
2012-08-08 14:48 1202在sql server中的如下sql语句是正确的select ... -
SQL SERVER 2005 导出包含(INSERT INTO)数据的SQL脚本 (使用存储过程)
2012-05-08 19:08 1458通常情况下,SQL Server里面的生成SQL脚本,只 ... -
正在检查操作系统要求...要求的结果: 5.0,5.1,5.2,6.0 之一..
2012-04-11 10:43 18349在win7 下安装oracle_11gR1_databa ... -
java备份mysql数据库
2011-06-13 16:45 996package com.zjx.dbbackup; /* ... -
MySQL 创建用户,授权,撤销,删除
2011-03-30 21:31 2215一, 创建用户: 命令:CREATE USER ... -
mysql left join 多个表
2011-03-16 17:09 37844SQL: select * from t_a a left ... -
Oracle数据库遍历树形结构表[转]
2011-03-01 13:31 17331、从根结点开始找子节 ...
相关推荐
通过上述步骤,我们可以实现一个高效、简洁且可重用的Struts分页功能。这种分页方式不仅能够有效提高系统的响应速度和用户体验,还能够更好地适应不同的开发环境和技术栈。此外,这种方式也更加符合MVC的设计理念,...
在JSP中,自定义标签库(Tag Library)是一种强大的工具,可以创建可重用的UI组件,例如我们的分页组件。 分页标签通常会包含以下关键元素: 1. **总记录数**:这是数据库中待分页的数据总数,用于计算总页数。 2....
6. **扩展性与可复用性**:为了实现代码的可重用性,我们可以创建一个通用的分页帮助类或辅助方法,供多个控制器和视图共享。这样,每次需要分页功能时,只需调用这个通用方法,就能轻松实现。 综上所述,这个"可...
"可重用的分页Bean"是一个设计精良的组件,它基于经典的三层架构(表现层、业务逻辑层、数据访问层)来实现,可以方便地在JSP MVC(模型-视图-控制器)框架中复用,提高代码的可维护性和效率。在这个PageBeanDemo中...
DisplayTag Portlet 1.1 是一个用于网页开发的开源分页库,它极大地简化了在Java Web应用程序中实现高效且美观的分页功能。这个jar包是DisplayTag项目的一个特定版本,专为portlet环境设计,portlet是Java Portal...
《C语言接口与实现--创建可重用软件的技术》是一本深入探讨如何通过C语言构建高效、可维护、可重用软件的专业书籍。在软件工程领域,可重用性是提高开发效率、降低维护成本的关键因素。这本书的核心目标就是教授读者...
"可重用的JAVA分页.rar"这个压缩包提供了一个简单且可复用的Java分页解决方案。 首先,我们来看`Pagination.java`,这是实现分页功能的核心类。它通常会包含如下的关键属性和方法: 1. **属性**:如总记录数...
`pager-taglib`是一个专为JSP页面设计的分页标签库,它简化了在JSP中实现分页的过程。下面将详细介绍`pager-taglib`的安装、使用方法以及其核心知识点。 ### 1. `pager-taglib`简介 `pager-taglib`是一个开源的JSP...
一个简单可重用的 React-Native 组件 :bug: 安装 yarn add react-native-error-boundary 用法 该组件在其子组件树中的任何位置捕获。 不处理本机错误。 使用这个组件非常简单。 首先,您必须导入ErrorBoundary组件...
总结起来,这个“一个用于分页的自定义标签”项目提供了在Java Web环境中高效、可重用的分页解决方案。通过自定义标签,开发者可以将复杂的分页逻辑封装起来,使JSP页面更加简洁,同时提高代码的可维护性和复用性。
本篇博客“自定义标签小练习----一个简单的分页标签”将深入探讨如何实现这样一个实用功能,通过自定义标签来实现网页的分页展示。 首先,我们要理解自定义标签的工作原理。自定义标签是JSP标准标签库(JSTL)的...
6. **分页组件重用**:为了实现分页的重用,你可以封装一个通用的分页组件,比如自定义的JSP标签。这个组件应该接受必要的参数(如页码、每页条数等),并负责生成分页链接和展示数据。 7. **URL参数设计**:合理...
《C语言接口与实现--创建可重用软件的技术》是一本深入探讨如何通过C语言构建高效、可维护和可重用软件的专业书籍。该书详细阐述了C语言在设计和实现模块化接口中的核心概念和技术,旨在帮助程序员提升代码质量,...
在QT编程中,QTableWidget是一个非常常用的控件,用于展示二维数据,但它本身并不支持内置的分页功能。在处理大量数据时,这可能会导致性能问题,因为所有的数据都会一次性加载到内存中。为了解决这个问题,我们可以...
C语言接口与实现--创建可重用软件的技术.pdf
本文将详细讲解如何实现一个很不错的自定义分页标签,以供开发者们参考和使用。 首先,我们要了解分页的基本原理。分页通常涉及到两个主要部分:前端显示和后端数据处理。前端负责展示当前页码、总页数以及翻页链接...
可重用性是软件工程中的一个重要概念,意味着代码可以在多个项目中重复使用,减少开发时间和成本。为了实现代码的可重用,我们需要遵循一些原则: 1. 抽象:通过封装细节,隐藏实现复杂性,只暴露必要的接口。 2. ...