[摘]通用的分页,可以参考点

一个新的Pageable接口及其实现
  首先,我们需要提供一个与java.sql.ResultSet向下兼容的接口,把它命名为Pageable,接口定义如下:
java 代码
  1. public interface Pageable extends java.sql.ResultSet{    
  2. /**返回总页数   
  3. */    
  4. int getPageCount();    
  5. /**返回当前页的记录条数   
  6. */    
  7. int getPageRowsCount();    
  8. /**返回分页大小   
  9. */    
  10. int getPageSize();    
  11. /**转到指定页   
  12. */    
  13. void gotoPage(int page) ;    
  14. /**设置分页大小   
  15. */    
  16. void setPageSize(int pageSize);    
  17. /**返回总记录行数   
  18. */    
  19. int getRowsCount();    
  20. /**   
  21. * 转到当前页的第一条记录   
  22. * @exception java.sql.SQLException 异常说明。   
  23. */    
  24. void pageFirst() throws java.sql.SQLException;    
  25. /**   
  26. * 转到当前页的最后一条记录   
  27. * @exception java.sql.SQLException 异常说明。   
  28. */    
  29. void pageLast() throws java.sql.SQLException;    
  30. /**返回当前页号   
  31. */    
  32. int getCurPage();    
  33. }    
  这是一个对java.sql.ResultSet进行了扩展的接口,主要是增加了对分页的支持,如设置分页大小,跳转到某一页,返回总页数等等。

  接着,我们需要实现这个接口,由于这个接口继承自ResultSet,并且它的大部分功能也都和ResultSet原有功能相同,所以这里使用了一个简单的Decorator模式。
java 代码
  1.   PageableResultSet2的类声明和成员声明如下:    
  2. public class PageableResultSet2 implements Pageable {    
  3. protected java.sql.ResultSet rs=null;    
  4. protected int rowsCount;    
  5. protected int pageSize;    
  6. protected int curPage;    
  7. protected String command = "";    
  8. }   

  可以看到,在PageableResultSet2中,包含了一个ResultSet的实例(这个实例只是实现了ResultSet接口,事实上它是由各个 数据库厂商分别实现的),并且把所有由ResultSet继承来的方法都直接转发给该实例来处理。
java 代码
  1. PageableResultSet2中继承自ResultSet的主要方法:    
  2. //……    
  3. public boolean next() throws SQLException {    
  4. return rs.next();    
  5. }    
  6. //……    
  7. public String getString(String columnName) throws SQLException {    
  8. try {    
  9. return rs.getString(columnName);    
  10. }    
  11. catch (SQLException e) {//这里是为了增加一些出错信息的内容便于调试    
  12. throw new SQLException (e.toString()+" columnName="    
  13. +columnName+" SQL="+this.getCommand());    
  14. }    
  15. }    
  16. //……    
  
  只有在Pageable接口中新增的方法才需要自己的写方法处理。
java 代码
  1. /**方法注释可参考Pageable.java   
  2. */    
  3. public int getCurPage() {    
  4. return curPage;    
  5. }    
  6. public int getPageCount() {    
  7. if(rowsCount==0return 0;    
  8. if(pageSize==0return 1;    
  9. //calculate PageCount    
  10. double tmpD=(double)rowsCount/pageSize;    
  11. int tmpI=(int)tmpD;    
  12. if(tmpD>tmpI) tmpI++;    
  13. return tmpI;    
  14. }    
  15. public int getPageRowsCount() {    
  16. if(pageSize==0return rowsCount;    
  17. if(getRowsCount()==0return 0;    
  18. if(curPage!=getPageCount()) return pageSize;    
  19. return rowsCount-(getPageCount()-1)*pageSize;    
  20. }    
  21. public int getPageSize() {    
  22. return pageSize;    
  23. }    
  24. public int getRowsCount() {    
  25. return rowsCount;    
  26. }    
  27. public void gotoPage(int page) {    
  28. if (rs == null)    
  29. return;    
  30. if (page < 1)    
  31. page = 1;    
  32. if (page > getPageCount())    
  33. page = getPageCount();    
  34. int row = (page - 1) * pageSize + 1;    
  35. try {    
  36. rs.absolute(row);    
  37. curPage = page;    
  38. }    
  39. catch (java.sql.SQLException e) {    
  40. }    
  41. }    
  42. public void pageFirst() throws java.sql.SQLException {    
  43. int row=(curPage-1)*pageSize+1;    
  44. rs.absolute(row);    
  45. }    
  46. public void pageLast() throws java.sql.SQLException {    
  47. int row=(curPage-1)*pageSize+getPageRowsCount();    
  48. rs.absolute(row);    
  49. }    
  50. public void setPageSize(int pageSize) {    
  51. if(pageSize>=0){    
  52. this.pageSize=pageSize;    
  53. curPage=1;    
  54. }    
  55. }    
  56.   PageableResultSet2的构造方法:    
  57. public PageableResultSet2(java.sql.ResultSet rs) throws java.sql.SQLException {    
  58. if(rs==nullthrow new SQLException("given ResultSet is NULL","user");    
  59.   
  60. rs.last();    
  61. rowsCount=rs.getRow();    
  62. rs.beforeFirst();    
  63.   
  64. this.rs=rs;    
  65. }    
  这里只是简单的取得一个总记录数,并将记录游标移回初始位置(before first),同时将参数中的ResultSet赋给成员变量。
Pageable的使用方法
  因为Pageable接口继承自ResultSet,所以在使用方法上与ResultSet一致,尤其是在不需要分页功能的时候,可以直接当成ResultSet使用。而在需要分页时,只需要简单的setPageSize, gotoPage,即可。
java 代码
  1. PreparedStatement pstmt=null;    
  2. Pageable rs=null;    
  3. ……//构造SQL,并准备一个pstmt.    
  4. rs=new PageableResultSet2(pstmt.executeQuery());//构造一个Pageable    
  5. rs.setPageSize(20);//每页20个记录    
  6. rs.gotoPage(2);//跳转到第2页    
  7. for(int i=0; i<rs.getPageRowsCount(); i++){//循环处理    
  8. int id=rs.getInt(“ID”);    
  9. ……//继续处理    
  10. }    


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

你可能感兴趣的:(java,oracle,sql,mysql,jsp)