`
yanguz123
  • 浏览: 568650 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java 分页

 
阅读更多

 

一.逻辑分页

 

1.逻辑分页的第一种方式,利用ResultSet的滚动分页。步骤如下:

 a.根据条件sql查询数据库。

 b.得到ResultSet的结果集,由于ResultSet带有游标,因此可以使用其next()方法来指向下一条记录。

 c.利用next()方法,得到分页所需的结果集。

 

 这种分页方式依靠的是对结果集的算法来分页,因此通常被称为“逻辑分页”。

 

 代码如下:

 

 

/** *//**

 * TestPageResultSetDAO.java

 *

 * Copyright 2008. All Rights Reserved.

 */

package com.cosmow.pageresultset.dao;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

 

import com.cosmow.pageresultset.entity.Bars;

 

/** *//**

 * TODO dao class TestPageResultSetDAO

 * 

 * Revision History

 * 

 * 2008-7-7,Cosmo,created it

 */

public class TestPageResultSetDAO {

 

    private final String FIND_BARS_PAGE = "SELECT * FROM YYBARS ORDER BY id";

 

    /** *//**

     * 提供JDBC连接方法,返回一个Connection的实例

     * 

     * @return

     * @throws SQLException

     */

    private Connection getConnection() throws SQLException {

        try {

            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";

            final String user = "store";

            final String password = "store_password";

            Class.forName("oracle.jdbc.driver.OracleDriver");

            Connection con = DriverManager.getConnection(url, user, password);

            return con;

        } catch (ClassNotFoundException e) {

            throw new SQLException(e.getMessage());

        }

    }

 

    /** *//**

     * 逻辑分页方法一,该方法使用移位(rs.next)来进行

     * 

     * @param currentPage

     *            当前页

     * @param showRows

     *            一页显示的数据量

     */

    public List<Bars> pageListOne(int currentPage, int showRows) {

        Connection con = null;

        PreparedStatement ps = null;

        ResultSet rs = null;

        ArrayList<Bars> resultList = new ArrayList<Bars>();

        try {

            con = getConnection();

            ps = con.prepareStatement(FIND_BARS_PAGE);

            rs = ps.executeQuery();

            // 过滤结果集的变量

            int skipBegin = (currentPage - 1) * showRows;

            int skipEnd = currentPage * showRows;

            // 翻页计数器

            int currentNum = 0;

            // 当返回结果集中有记录时

            while (rs.next()) {

                // 以下情况将保证在结果集中有记录时的应用

                if (currentNum >= skipBegin && currentNum < skipEnd) {

                    Bars bar = new Bars();

                    bar.setId(rs.getLong("id"));

                    bar.setName(rs.getString("name"));

                    bar.setType(rs.getInt("type"));

                    bar.setCreatorId(rs.getLong("creator_id"));

                    resultList.add(bar);

                    if (currentNum == skipEnd - 1)

                        break;

                }

                currentNum++;

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            try {

                if (rs != null)

                    rs.close();

                if (ps != null)

                    ps.close();

                if (con != null)

                    con.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

        return resultList;

    }

}

 

 

 

 

 

2.逻辑分页的第二种方式

利用Scrollable ResultSets(可滚动结果集合)来快速定位到某个游标所指定的记录行,所使用的是ResultSet的absolute()方法。

改进代码如下:

 

/** *//**

 * TestPageResultSetDAO.java

 *

 * Copyright 2008. All Rights Reserved.

 */

package com.cosmow.pageresultset.dao;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

 

import com.cosmow.pageresultset.entity.Bars;

 

/** *//**

 * TODO dao class TestPageResultSetDAO

 * 

 * Revision History

 * 

 * 2008-7-7,Cosmo,created it

 */

public class TestPageResultSetDAO {

 

    private final String FIND_BARS_PAGE = "SELECT * FROM YYBARS ORDER BY id";

 

    /** *//**

     * 提供JDBC连接方法,返回一个Connection的实例

     * 

     * @return

     * @throws SQLException

     */

    private Connection getConnection() throws SQLException {

        try {

            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";

            final String user = "store";

            final String password = "store_password";

            Class.forName("oracle.jdbc.driver.OracleDriver");

            Connection con = DriverManager.getConnection(url, user, password);

            return con;

        } catch (ClassNotFoundException e) {

            throw new SQLException(e.getMessage());

        }

    }

 

    /** *//**

     * 逻辑分页方法二,使用absolute()方法分页

     * 

     * @param currentPage

     *            当前页

     * @param showRows

     *            一页显示的数据量

     */

    public List<Bars> pageListTwo(int currentPage, int showRows) {

        Connection con = null;

        PreparedStatement ps = null;

        ResultSet rs = null;

        ArrayList<Bars> resultList = new ArrayList<Bars>();

        try {

            con = getConnection();

            ps = con.prepareStatement(FIND_BARS_PAGE);

            rs = ps.executeQuery();

 

            // 过滤结果集的变量

            int skipBegin = (currentPage - 1) * showRows;

            int skipEnd = currentPage * showRows;

            // 利用rs.absolute进行定位

            if (!rs.absolute(skipBegin))

                return resultList;

            // 当返回结果集中有记录时

            while (rs.next()) {

                // 以下情况将保证在结果集中有记录时的应用

                if (skipBegin < skipEnd) {

                    Bars bar = new Bars();

                    bar.setId(rs.getLong("id"));

                    bar.setName(rs.getString("name"));

                    bar.setType(rs.getInt("type"));

                    bar.setCreatorId(rs.getLong("creator_id"));

                    resultList.add(bar);

                    if (skipBegin == skipEnd - 1)

                        break;

                }

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            try {

                if (rs != null)

                    rs.close();

                if (ps != null)

                    ps.close();

                if (con != null)

                    con.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

        return resultList;

    }

}

 

 

虽然和第一种方式区别不大,单效率比ResultSet滚动要好,但是absolute()方法并不是所有jdbc驱动都支持。

可用如下代码测试当前jdbc驱动是否支持可滚动结果集:

 

int type = rs.getType();

if (type == ResultSet.TYPE_SCROLL_INSENSITIVE || type == ResultSet.TYPE_SCROLL_SENSITIVE)

    System.out.println("Result set is scrollable");

else

    System.out.println("Result set is not scrollable");

 

 

二.物理分页

利用数据库本身的一些特性来分页。即:利用了数据库对sql语法的优化,提高分页性能。

1.针对Oracle数据库

步骤如下:

a.根据所使用的数据库特性来组织sql进行分页。

b.每次跳转页面的sql查询都不相同。

 通用的sql分页方式,“限制行数结果集的倒序”分页,步骤如下:

 (1).取得符合条件的所有结果集中可以唯一标识的Key值(通常是主键),并正向排序。

 (2).利用数据库提供的特殊方法进行“最大结果集”的限制(在Oracle中使用rownum, sql server中使用top, mysql中使用limit...),

 该“最大结果集”指包含当前所处页的所有记录数,“最大结果集”应该只包含惟一的Key值。

 (3).对步骤(2)中的“最大结果集”进行逆序,并取得“显示当前页显示数量的结果集”,该结果集中只包含惟一的Key值。

 (4).通过步骤(3)中所取得的Key值取得显示数据,该显示数据就是当前页应该显示的数据。

 

代码如下:

 

 

/** *//**

 * TestPageResultSetDAO.java

 *

 * Copyright 2008. All Rights Reserved.

 */

package com.cosmow.pageresultset.dao;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

 

import com.cosmow.pageresultset.entity.Bars;

 

/** *//**

 * TODO dao class TestPageResultSetDAO

 * 

 * Revision History

 * 

 * 2008-7-7,Cosmo,created it

 */

public class TestPageResultSetDAO {

 

    //针对Oracle

    private final String FIND_BARS_ORACLE = "select b3.* from "

            + "(select b1.id from "

            + "(select b.id from yybars b where rownum <= ? order by b.id desc) b1 "

            + "where rownum <= ? order by b1.id desc) b2, "

            + "yybars b3 where b2.id = b3.id order by b2.id";

 

    /** *//**

     * 提供JDBC连接方法,返回一个Connection的实例

     * 

     * @return

     * @throws SQLException

     */

    private Connection getConnection() throws SQLException {

        try {

            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";

            final String user = "store";

            final String password = "store_password";

            Class.forName("oracle.jdbc.driver.OracleDriver");

            Connection con = DriverManager.getConnection(url, user, password);

            return con;

        } catch (ClassNotFoundException e) {

            throw new SQLException(e.getMessage());

        }

    }

 

    /** *//**

     * 物理分页方法一针对Oracle,使用sql语句的id查询来进行

     * 

     * @param currentPage

     *            当前页

     * @param showRows

     *            一页显示的数据量

     */

    public List<Bars> pageListThree(int currentPage, int showRows) {

        Connection con = null;

        PreparedStatement ps = null;

        ResultSet rs = null;

        ArrayList<Bars> resultList = new ArrayList<Bars>();

        try {

            con = getConnection();

            ps = con.prepareStatement(FIND_BARS_ORACLE);

            //传入参数,第一个参数标示包含该页总共有几条数据

            ps.setInt(1, showRows * currentPage);

            //第二个参数标示将取得在第一个参数所指定的数据中应该显示的数据

            ps.setInt(2, showRows);

            rs = ps.executeQuery();

            // 当返回结果集中有记录时

            while (rs.next()) {

                Bars bar = new Bars();

                bar.setId(rs.getLong("id"));

                bar.setName(rs.getString("name"));

                bar.setType(rs.getInt("type"));

                bar.setCreatorId(rs.getLong("creator_id"));

                resultList.add(bar);

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            try {

                if (rs != null)

                    rs.close();

                if (ps != null)

                    ps.close();

                if (con != null)

                    con.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

        return resultList;

    }

}

 

 

 

 

2.针对MySQL数据库

在MySQL数据库中offset关键字的意思是"越过",而limit关键字的意思是“限制”,利用这两者结合可轻松分页。

(1)取得符合条件的结果集,包含全字段。

(2)利用offset关键字越过一段结果集(被越过的结果集就是"(当前页 - 1) * 一页显示数")。

(3)利用limit关键字限制取得一段结果集(被限制取得的结果集就是一页显示数)

 

代码如下:

 

 

/** *//**

 * TestPageResultSetDAO.java

 *

 * Copyright 2008. All Rights Reserved.

 */

package com.cosmow.pageresultset.dao;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

 

import com.cosmow.pageresultset.entity.Bars;

 

/** *//**

 * TODO dao class TestPageResultSetDAO

 * 

 * Revision History

 * 

 * 2008-7-7,Cosmo,created it

 */

public class TestPageResultSetDAO {

 

    private final String FIND_BARS_MYSQL = "select * from yybars order by id limit ? offset ?";

 

 

    /** *//**

     * 提供JDBC连接方法,返回一个Connection的实例

     * 

     * @return

     * @throws SQLException

     */

    private Connection getConnection() throws SQLException {

        try {

            final String url = "jdbc:oracle:thin:@localhost:1521:ORCL";

            final String user = "store";

            final String password = "store_password";

            Class.forName("oracle.jdbc.driver.OracleDriver");

            Connection con = DriverManager.getConnection(url, user, password);

            return con;

        } catch (ClassNotFoundException e) {

            throw new SQLException(e.getMessage());

        }

    }

 

    /** *//**

     * 物理分页方法二针对mysql,使用sql语句的limit和offset来进行分页

     * 

     * @param currentPage

     *            当前页

     * @param showRows

     *            一页显示的数据量

     */

    public List<Bars> pageListFour(int currentPage, int showRows) {

        Connection con = null;

        PreparedStatement ps = null;

        ResultSet rs = null;

        ArrayList<Bars> resultList = new ArrayList<Bars>();

        try {

            con = getConnection();

            ps = con.prepareStatement(FIND_BARS_MYSQL);

            //传入参数,第一个参数表示显示几条记录(limit关键字的含义)

            ps.setInt(1, showRows);

            //第二个参数表示丢弃几条记录(offset关键字的含义)

            ps.setInt(2, showRows * (currentPage - 1));

            rs = ps.executeQuery();

            // 当返回结果集中有记录时

            while (rs.next()) {

                Bars bar = new Bars();

                bar.setId(rs.getLong("id"));

                bar.setName(rs.getString("name"));

                bar.setType(rs.getInt("type"));

                bar.setCreatorId(rs.getLong("creator_id"));

                resultList.add(bar);

            }

        } catch (SQLException e) {

            e.printStackTrace();

        } finally {

            try {

                if (rs != null)

                    rs.close();

                if (ps != null)

                    ps.close();

                if (con != null)

                    con.close();

            } catch (SQLException e) {

                e.printStackTrace();

            }

        }

        return resultList;

    }

}

 

 

 

 

分页结论:

1.物理分页速度上并不一定快于逻辑分页,逻辑分页速度上也并不一定快于物理分页。

2.物理分页总是优于逻辑分页:没有必要将属于数据库端的压力加诸到应用端来,就算速度上存在优势,

然而其它性能上的优点足以弥补这个缺点。

3.在分页工作前,有必要了解使用数据库本身的一些sql语句特点更好的分页。

 

 

 

ava通用分页

一. 要分页我们必须要有数据库,所以我们先准备下数据库,其数据库脚步如下:

--以下是创建数据库和数据库表以及向数据库插入数据  

use master  

Go  

if exists(select * from sysdatabases where name='pagination')  

drop database pagination  

Go  

create database pagination  

Go  

use pagination  

Go  

create table userInfo (  

    [userID] int identity(1,1) primary key not null,  

    [userName] nvarchar(50) not null,  

    [userPassword] nvarchar(50) not null,  

)  

Go  

insert userInfo  values('xuyesheng','8888')  

insert userInfo  values('jiaojiao','8888')  

insert userInfo  values('administrator','888')  

insert userInfo  values('xuyesheng1','123')  

insert userInfo  values('xuyesheng2','123')  

insert userInfo  values('xuyesheng3','123')  

insert userInfo  values('xuyesheng4','123')  

insert userInfo  values('xuyesheng5','123')  

insert userInfo  values('xuyesheng6','123')  

Go  

select * from userInfo

二: 通用分页的存储过程,如下:

    ---------------创建存储过程--------------  

    Go  

    set ANSI_NULLS ON  

    set QUOTED_IDENTIFIER ON  

    go  

    ------------------------------------  

    --  

    --用途:用于需要分页显示的数据  

    --时间:2009年08月22日  

    --描述:通用的存储过程分页程序  

    --  

    -------------------------------------  

    create PROCEDURE [dbo].[GetData]  

    @tblName varchar(255), -- 表名  

    @fldName varchar(255), -- 字段名  

    @OrderfldName varchar(255), -- 排序字段名  

    @PageSize int = 10, -- 页尺寸  

    @PageIndex int = 1, -- 页码  

    @IsCount bit = 0, -- 返回记录总数, 非 0 值则返回  

    @OrderType bit = 0, -- 设置排序类型, 非 0 值则降序  

    @strWhere varchar(1000) = '' -- 查询条件 (注意: 不要加 where)  

    AS  

    declare @strSQL varchar(6000) -- 主语句  

    declare @strTmp varchar(500) -- 临时变量  

    declare @strOrder varchar(400) -- 排序类型  

    if @OrderType != 0  

    begin  

      set @strTmp = '<(select min'  

      set @strOrder = ' order by [' + @OrderfldName +'] desc'  

    end  

    else  

    begin  

      set @strTmp = '>(select max'  

      set @strOrder = ' order by [' + @OrderfldName +'] asc'  

    end  

      set @strSQL = 'select top ' + str(@PageSize) + ' ' + @fldName + ' from ['  

      + @tblName + '] where [' + @OrderfldName + ']' + @strTmp + '(['  

      + @OrderfldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['  

      + @OrderfldName + '] from [' + @tblName + ']' + @strOrder + ') as tblTmp)'  

      + @strOrder  

      if @strWhere != ''  

      set @strSQL = 'select top ' + str(@PageSize) + ' ' + @fldName + ' from ['  

      + @tblName + '] where [' + @OrderfldName + ']' + @strTmp + '(['  

      + @OrderfldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['  

      + @OrderfldName + '] from [' + @tblName + '] where ' + @strWhere + ' '  

      + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder  

      if @PageIndex = 1  

      begin  

       set @strTmp = ''  

       if @strWhere != ''  

          set @strTmp = ' where ' + @strWhere  

          set @strSQL = 'select top ' + str(@PageSize) + ' ' + @fldName + ' from ['  

          + @tblName + ']' + @strTmp + ' ' + @strOrder  

      end  

      if @IsCount != 0  

      begin  

           if @strWhere != ''  

            set @strSQL = 'select count(' + @OrderfldName + ') as Total from [' + @tblName + ']'+ ' where ' + @strWhere    

            else  

            set @strSQL = 'select count(' + @OrderfldName + ') as Total from [' + @tblName + ']'      

      end  

    exec (@strSQL)  

    --测试下  

    Go  

    ----参数说明exec [GetData] '表明','查找的列名* 表示查找所有信息','主键',页大小,第几页,非  

    --表示返回记录数,[排序类型,非则降序排列],条件  

    --得到分页的数据  

    exec [GetData] 'userInfo','*','userID',5,1,0,0,null  

    --得到总共的条数  

    exec [GetData] 'userInfo','*','userID',5,1,1,0,null  

    --根据条件查询  

    exec [GetData] 'userInfo','*','userID',5,1,0,0,' userID like ''%2%'' '

存储过程我们有了我们只要给一下几个参数就OK了

@tblName varchar  -- 表名

@fldName varchar  -- 字段名

@OrderfldName     -- 排序字段名

@PageSize int     -- 页尺寸

@PageIndex int    -- 页码

@IsCount bit      -- 返回记录总数, 非 0 值则返回

@OrderType bit    -- 设置排序类型, 非 0 值则降序

@strWhere varchar -- 查询条件 (注意: 不要加 where)

 

三 通用包

到这里我们先不用急,先将一下三个Java类(Pagination.java Call.java AutoSetData.java)封装一下,然后打成JAR包,以后我们直接导入JAR包即可

Pagination.java

存储过程我们有了我们只要给一下几个参数就OK了

@tblName varchar  -- 表名

@fldName varchar  -- 字段名

@OrderfldName     -- 排序字段名

@PageSize int     -- 页尺寸

@PageIndex int    -- 页码

@IsCount bit      -- 返回记录总数, 非 0 值则返回

@OrderType bit    -- 设置排序类型, 非 0 值则降序

@strWhere varchar -- 查询条件 (注意: 不要加 where)

到这里我们先不用急,先将一下三个Java类(Pagination.java Call.java AutoSetData.java)封装一下,然后打成JAR包,以后我们直接导入JAR包即可

Pagination.java

 

import java.util.List;  

public class Pagination {  

    // 总共的数据量  

    private int totle;  

    // 每页显示多少条  

    private int pageSize;  

    // 共有多少页  

    private int totlePage;  

    // 当前是第几页  

    private int index;  

    // 数据  

    private List data;  

    // 连接路径  

    private String path;  

    public void setTotle(int totle) {  

        this.totle = totle;  

    }  

    public void setPageSize(int pageSize) {  

        this.pageSize = pageSize;  

    }  

    public void setIndex(int index) {  

        this.index = index;  

    }  

    public void setPath(String path) {  

        this.path = path;  

    }  

    public int getTotle() {  

        return totle;  

    }  

    public int getPageSize() {  

        return pageSize;  

    }  

    public int getTotlePage() {  

        return (this.totle + this.pageSize - 1) / this.pageSize;  

    }  

    public int getIndex() {  

        return index;  

    }  

    public List getData() {  

        return data;  

    }  

    public void setData(List data) {  

        this.data = data;  

    }  

    public String getPageDisplay() {  

        StringBuffer displayInfo = new StringBuffer();  

        if (index == 0 || pageSize == 0) {  

            displayInfo.append("没有分页的信息!");  

        } else {  

            displayInfo.append("<div class='pager'>");  

            displayInfo.append("共" + totle + "条记录每页<span style="color:#FF0000" mce_style="color:#FF0000">" + pageSize  

                    + "</span>条");  

            displayInfo.append("第<span style="color:#FF0000" mce_style="color:#FF0000">" + index  

                    + "</span>页/共"  

                    + this.getTotlePage() + "页");  

            // 判断如果当前是第一页 则“首页”和“第一页”失去链接  

            if (index == 1) {  

                displayInfo.append("  首页 ");  

                displayInfo.append("上一页 ");  

            } else {  

                displayInfo.append("  <a href="" + path  

                        + "index=1" mce_href="" + path  

                        + "index=1">首页</a> ");  

                displayInfo.append("<a href="" + path + "index=" + (index - 1)  

                        + "" mce_href="" + path + "index=" + (index - 1)  

                        + "">上一页</a> ");  

            }  

            if (index >= this.getTotlePage()) {  

                displayInfo.append("下一页 ");  

                displayInfo.append("最后一页 ");  

            } else {  

                displayInfo.append("<a href="" + path + "index=" + (index + 1)  

                        + "" mce_href="" + path + "index=" + (index + 1)  

                        + "">下一页</a> ");  

                displayInfo.append("<a href="" + path + "index="  

                        + this.getTotlePage() + "" mce_href="" + path + "index="  

                        + this.getTotlePage() + "">最后一页</a> ");  

            }  

            displayInfo.append("</div>");  

        }  

        return displayInfo.toString();  

    }  

}    

 

Pagination.java文件源码我们有了,下面的是Call.java类的源码:

 

import java.sql.Connection;  

import java.sql.DriverManager;  

import java.sql.ResultSet;  

import java.sql.SQLException;  

import java.util.ArrayList;  

import java.util.Collection;  

import java.util.Iterator;  

import java.util.List;  

public class Call {  

    private AutoSetData auto = new AutoSetData();  

 

    public List execProcedure(String driver, String url, String userName,  

            String pwd, Object[] ob, Class c) {  

        try {  

            Class.forName(driver);  

            Connection conn = DriverManager.getConnection(url, userName, pwd);  

            String sql = "exec GetData ?,?,?,?,?,?,?,null";  

            List list = new ArrayList();  

            // Ltest是我测试用类,实际操作请注入相关对象,支持set,get,is,read,writer为前缀数据对,更多请继续添加。  

            Collection collection = auto.get(conn, c.newInstance().getClass(),  

                    sql, ob);  

            for (Iterator it = collection.iterator(); it.hasNext();) {  

                Object obj = c.newInstance();  

                list.add(it.next());  

            }  

            return list;  

        } catch (Exception e) {  

            e.printStackTrace();  

        }  

        return null;  

    }  

 

}  

 

AutoSetData.java 自动将数据封装到实体类中

 

import java.lang.reflect.Method;  

import java.lang.reflect.Modifier;  

import java.sql.CallableStatement;  

import java.sql.Connection;  

import java.sql.ResultSet;  

import java.sql.ResultSetMetaData;  

import java.sql.SQLException;  

import java.util.ArrayList;  

import java.util.Collection;  

public class AutoSetData {  

 

    private Object[] beanMatch(Class clazz, String beanProperty) {  

        Object[] result = new Object[2];  

        char beanPropertyChars[] = beanProperty.toCharArray();  

        beanPropertyChars[0] = Character.toUpperCase(beanPropertyChars[0]);  

        String s = new String(beanPropertyChars);  

        String names[] = { ("set" + s).intern(), ("get" + s).intern(),  

                ("is" + s).intern(), ("write" + s).intern(),  

                ("read" + s).intern() };  

        Method getter = null;  

        Method setter = null;  

        Method methods[] = clazz.getMethods();  

        for (int i = 0; i < methods.length; i++) {  

            Method method = methods[i];  

            // 只取公共字段  

            if (!Modifier.isPublic(method.getModifiers()))  

                continue;  

            String methodName = method.getName().intern();  

            for (int j = 0; j < names.length; j++) {  

                String name = names[j];  

                if (!name.equals(methodName))  

                    continue;  

                if (methodName.startsWith("set")  

                        || methodName.startsWith("read"))  

                    setter = method;  

                else  

                    getter = method;  

            }  

        }  

        result[0] = getter;  

        result[1] = setter;  

        return result;  

    }  

 

    private void beanRegister(Object object, String beanProperty, String value) {  

        Object[] beanObject = beanMatch(object.getClass(), beanProperty);  

        Object[] cache = new Object[1];  

        Method getter = (Method) beanObject[0];  

        Method setter = (Method) beanObject[1];  

        try {  

            // 通过get获得方法类型  

            String methodType = getter.getReturnType().getName();  

            if (methodType.equalsIgnoreCase("long")) {  

                cache[0] = new Long(value);  

                setter.invoke(object, cache);  

            } else if (methodType.equalsIgnoreCase("int")  

                    || methodType.equalsIgnoreCase("integer")) {  

                cache[0] = new Integer(value);  

                setter.invoke(object, cache);  

            } else if (methodType.equalsIgnoreCase("short")) {  

                cache[0] = new Short(value);  

                setter.invoke(object, cache);  

            } else if (methodType.equalsIgnoreCase("float")) {  

                cache[0] = new Float(value);  

                setter.invoke(object, cache);  

            } else if (methodType.equalsIgnoreCase("double")) {  

                cache[0] = new Double(value);  

                setter.invoke(object, cache);  

            } else if (methodType.equalsIgnoreCase("boolean")) {  

                cache[0] = new Boolean(value);  

                setter.invoke(object, cache);  

            } else if (methodType.equalsIgnoreCase("java.lang.String")) {  

                cache[0] = value;  

                setter.invoke(object, cache);  

            } else if (methodType.equalsIgnoreCase("java.io.InputStream")) {  

            } else if (methodType.equalsIgnoreCase("char")) {  

                cache[0] = (Character.valueOf(value.charAt(0)));  

                setter.invoke(object, cache);  

            }  

        } catch (Exception e) {  

            e.printStackTrace();  

        }  

    }  

 

    public Collection get(final Connection connection, final Class clazz,  

             String sql,Object[] obj) {  

        // 创建PreparedStatement  

        CallableStatement  ptmt = null;  

        // 创建resultset  

        ResultSet rset = null;  

        // 创建collection  

        Collection collection = null;  

        try {  

            // 赋予实例  

            ptmt = connection.prepareCall(sql);  

            for (int i = 1; i <= obj.length; i++) {  

                ptmt.setObject(i,obj[i-1]);  

            }  

            rset = ptmt.executeQuery();  

            collection = get(rset, clazz);  

        } catch (SQLException e) {  

            System.err.println(e.getMessage());  

        } finally {  

            try {  

                // 关闭rs并释放资源  

                if (rset != null) {  

                    rset.close();  

                    rset = null;  

                }  

                // 关闭ps并释放资源  

                if (ptmt != null) {  

                    ptmt.close();  

                    ptmt = null;  

                }  

            } catch (SQLException e) {  

                System.err.println(e.getMessage());  

            }  

        }  

        return collection;  

    }  

    public Collection get(final ResultSet result, final Class clazz) {  

        // 创建collection  

        Collection collection = null;  

        try {  

            ResultSetMetaData rsmd = result.getMetaData();  

            // 获得数据列数  

            int cols = rsmd.getColumnCount();  

            // 创建等同数据列数的arraylist类型collection实例  

            collection = new ArrayList(cols);  

            // 遍历结果集  

            while (result.next()) {  

                // 创建对象  

                Object object = null;  

                try {  

                    // 从class获得对象实体  

                    object = clazz.newInstance();  

                } catch (Exception e) {  

                }  

                // 循环每条记录  

                for (int i = 1; i <= cols; i++) {  

                    beanRegister(object, rsmd.getColumnName(i), result  

                            .getString(i));  

                }  

                // 将数据插入collection  

                collection.add(object);  

            }  

        } catch (SQLException e) {  

            System.err.println(e.getMessage());  

        } finally {  

        }  

        return collection;  

    }  

}  

 

看这里我们引入了jstl.jar standard.jar sqljdbc.jar pagination.jar四个jar包 缺一不可奥。

下面我们创建一个实体类,代码如下: 

public class UserInfo {  

    private int userID;  

    private String userName;  

    private String userPassword;  

 public int getUserID() {  

  return userID;  

 }  

 public void setUserID(int userID) {  

  this.userID = userID;  

 }  

 public String getUserName() {  

  return userName;  

 }  

 public void setUserName(String userName) {  

  this.userName = userName;  

 }  

 public String getUserPassword() {  

  return userPassword;  

 }  

 public void setUserPassword(String userPassword) {  

  this.userPassword = userPassword;  

 }  

 

}  

 

 

实体类我们创建完毕,现在我们创建servlet:

 

import java.io.IOException;  

import java.util.ArrayList;  

import java.util.List;  

import javax.servlet.ServletException;  

import javax.servlet.http.HttpServlet;  

import javax.servlet.http.HttpServletRequest;  

import javax.servlet.http.HttpServletResponse;  

import com.ant.util.Call;  

import com.ant.util.Pagination;  

import com.xuyesheng.entity.UserInfo;  

public class PageServlet extends HttpServlet {  

 

 public void doGet(HttpServletRequest request, HttpServletResponse response)  

   throws ServletException, IOException {  

  this.doPost(request, response);  

 }  

 public void doPost(HttpServletRequest request, HttpServletResponse response)  

   throws ServletException, IOException {  

  //取得jsp页面传递来的页数,参数名 index 不可更改  

  String index = request.getParameter("index");  

  int num = 0;  

  if (index == null) {  

   num = 1;  

  } else {  

   num = Integer.parseInt(index);  

  }  

  //创建封装数据类的对象 call  

  Call call = new Call();  

  //创建数组存储 存储过程的参数  

  Object obj[] = { "userInfo", "*", "userID", 5, num+"", 0+"", 0+"" };  

  //调用执行存储过程的方法  

  List li = call.execProcedure(  

    "com.microsoft.sqlserver.jdbc.SQLServerDriver",  

    "jdbc:sqlserver://localhost:1433;databaseName=pagination",  

    "sa", "as", obj, UserInfo.class);  

  //保存用户名  

  List<String> list = new ArrayList<String>();  

  //便利集合  

  for (int i = 0; i < li.size(); i++) {  

   UserInfo ui = (UserInfo) li.get(i);  

   list.add(ui.getUserName());  

   list.add(ui.getUserPassword());  

  }  

  //创建 分页对象  

  Pagination p = new Pagination();  

  //设置页数  

  p.setIndex(num);  

  //设置页大小  

  p.setPageSize(Integer.parseInt(obj[3].toString()));  

  //设置总共的条数  

  p.setTotle(call.getTotle());  

  //设置数据  

  p.setData(list);  

  //跳转的路径  

  p.setPath("page.do?");  

  request.setAttribute("page", p);  

  request.getRequestDispatcher("index.jsp").forward(request, response);  

 }  

}  

 

 

到这里我们就差一个页面了:

页面代码如下: 

<%@ page language="java"  pageEncoding="GBK"%>  

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  

<html>  

  <head>  

    <title>java通用分页显示数据</title>  

  </head>  

  <body>  

 <table width="507" height="160" border="1" align="center" cellpadding="0" cellspacing="0" bordercolor="#999900">  

         <tr>  

           <td  height="40" align="center" valign="middle" bgcolor="#FF9999"><h2>许业生用java实现通用分页功能</h2></td>  

         </tr>  

         <tr>  

           <td  height="35" align="center" valign="middle" bgcolor="#FF9999"><h3>用户名</h3></td>  

 

         </tr>  

          <c:forEach items="${requestScope.page.data}" var="li" >  

         <tr>  

           <td height="35" align="center" valign="middle" bgcolor="#CC99CC" >  

      <c:out value="${li}"/>  

    </td>  

         </tr>  

         </c:forEach>  

         <tr>  

           <td height="40"  align="center" valign="middle" ><c:out value="${requestScope.page.pageDisplay}" escapeXml="false"/></td>  

         </tr>  

       </table>  

  </body>  

</html>  

 

其中web.xml文件中的servlet的路径配置如下:

 

  <?xml version="1.0" encoding="UTF-8"?>  

<web-app version="2.4"  

 xmlns="http://java.sun.com/xml/ns/j2ee"  

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee  

 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  

  <servlet>  

    <description>通用分页Servlet</description>  

    <servlet-name>PageServlet</servlet-name>  

    <servlet-class>com.xuyesheng.servlet.PageServlet</servlet-class>  

  </servlet>  

  <servlet-mapping>  

    <servlet-name>PageServlet</servlet-name>  

    <url-pattern>/page.do</url-pattern>  

  </servlet-mapping>  

  <welcome-file-list>  

    <welcome-file>index.jsp</welcome-file>  

  </welcome-file-list>  

</web-app>  

 

到这里我们的通用分页已经结束了,该怎么访问呢?

呵呵  大家肯定比我知道啦!http://localhost:8080/pagination/page.do

大功告成!谢谢给位光临!

 

然后我们将刚才的三个.java文件打成JAR包,下次我们用的时候直接导入这个jar包就行了

四:项目使用

现在我们新建一个项目测试一下如何使用:

在我们创建项目的时候给项目添加jstl标签支持,我们在页面会用到,项目框架如下:

 

 

=======================================================================================================================================

 

 

分页是被讨论的快烂了的问题,现在的分页组件页到处都是!像有名的disply EC等等.

最近有舍友问起来,我说用组件啊,不过毕业设计用那个好像不太合适!就自己写个!不过觉得不能叫组件,就是只能简单实现罢了,有时间再修改.

 

1.分页bean

packageuseBean;

importjava.sql.ResultSet;

importjava.util.List;

importbean.EvaluationBean;

publicclassPageDiv{

/**

*@paramargs

*/

privateintpageSize;

privateintpageNum;

privateintstartRow;

privateintendRow;

privateintrestPage;

privateintcurrentPage;

//获得当前页数用来实现翻页

publicintgetCurrentPage(){

returncurrentPage;

}

publicvoidsetCurrentPage(intcurrentPage){

this.currentPage=currentPage;

}

//获得最后一行

publicintgetEndRow(Listlist){

if(this.getCurrentPage()==this.pageNum){

this.endRow=this.getStartRow()+this.getRestPage(list)-1;

}

else{

this.endRow=this.getStartRow()+this.getPageSize()-1;

}

returnendRow;

}

publicvoidsetEndRow(intendRow){

this.endRow=endRow;

}

//获得总页数

publicintgetPageNum(Listlist){

if(list.size()%this.getPageSize()==0){

this.pageNum=list.size()/this.getPageSize();

}

else{

this.pageNum=list.size()/this.getPageSize()+1;

}

returnpageNum;

}

publicvoidsetPageNum(intpageNum){

this.pageNum=pageNum;

}

//设置每页显示的记录数

publicintgetPageSize(){

returnpageSize;

}

publicvoidsetPageSize(intpageSize){

this.pageSize=pageSize;

}

//获得起始行

publicintgetStartRow(){

startRow=(this.currentPage-1)*(this.pageNum)+1;

returnstartRow;

}

publicvoidsetStartRow(intstartRow){

this.startRow=startRow;

}

//获得剩余页数

publicintgetRestPage(Listlist){

if(list.size()%this.getPageSize()==0){

this.restPage=0;

}

else{

this.restPage=list.size()%this.getPageSize();

}

returnrestPage;

}

publicvoidsetRestPage(intrestPage){

this.restPage=restPage;

}

publicstaticvoidmain(String[]args){

//TODOAuto-generatedmethodstub

Link_dbld=newLink_db();

EvaluationBeane=newEvaluationBean();

Listlist=e.findEvByName("李建成");

System.out.println("共"+list.size()+"条记录");

PageDivpd=newPageDiv();

pd.setPageSize(5);

pd.setCurrentPage(2);

System.out.println("当前是"+pd.getCurrentPage()+"页");

System.out.println("共"+pd.getPageNum(list)+"页记录");

System.out.println("最后一页有"+pd.getRestPage(list)+"条记录");

System.out.println("本页的第一行是"+pd.getStartRow()+"条记录");

System.out.print("最后一行记录是第"+pd.getEndRow(list)+"条记录");

}

}

 

2.调用的serlet

publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)

throwsServletException,IOException{

response.setContentType("text/html");

PrintWriterout=response.getWriter();

Stringtname="";

ListlistVo=null;

if(request.getParameter("userName")!=null){

tname=request.getParameter("userName");

EvaluationBeaneb=newEvaluationBean();

listVo=eb.findEvByName(tname);

}

if(listVo.size()>0){

HttpSessionsession=request.getSession();

session.setAttribute("tname",tname);

session.setAttribute("list",listVo);

//RequestDispatcherrd=request.getRequestDispatcher("/WEB-INF/teacher.jsp");

//rd.forward(request,response);

response.sendRedirect("../teacher.jsp");

}

else{

RequestDispatcherrd=request.getRequestDispatcher("/WEB-INF/error.jsp");

rd.forward(request,response);

}

}

 

3.调用的jsp文件

<body>

<formaction=""name="form1">

<center>

<%

ListlistVo=(List)session.getAttribute("list");

Stringtname=(String)session.getAttribute("tname");

intaverageScore=0;

PageDivpd=newPageDiv();

pd.setPageSize(5);

intcurrentPage=1;

intpageNum=pd.getPageNum(listVo);

if(request.getParameter("currentPage")!=null){

currentPage=newInteger(request.getParameter("currentPage")).intValue();

}

pd.setCurrentPage(currentPage);

%>

<h2>

<%=tname%>"老师你好!

h2>

<fontstyle='font-size:8pt'>

当前是第<%=pd.getCurrentPage()%>页)

<br>

共<%=pd.getPageNum(listVo)%>页记录)

<br>

(共"<%=listVo.size()%>"项记录)

font>

<tablewidth='680'border='1'cellspacing='0'cellpadding='0'bordercolor='#B8D9F2'>

<tr>

<td><fontstyle='font-size:8pt'>

编号

td>

<td><fontstyle='font-size:8pt'>

分数

td>

<td><fontstyle='font-size:8pt'>

课程名称

td>

<td><fontstyle='font-size:8pt'>

教师名称

td>

<td><fontstyle='font-size:8pt'>

综合评语

td>

tr>

<%

for(inti=pd.getStartRow();i<pd.getEndRow(listVo)+1;i++){

TeacherVovo=(TeacherVo)listVo.get(i-1);

out.print("<tr>");

out.print("<td><fontstyle='font-size:8pt'>");

out.print(i);

out.print("td>");

out.print("<td><fontstyle='font-size:8pt'>");

out.print(vo.getAllScore());

out.print("td>");

out.print("<td><fontstyle='font-size:8pt'>");

out.print(vo.getCname());

out.print("td>");

out.print("<td><fontstyle='font-size:8pt'>");

out.print(vo.getTname());

out.print("td>");

out.print("<td><fontstyle='font-size:8pt'>");

out.print(vo.getCompre_reviews());

out.print("td>");

out.print("tr>");

}

%>

<tr>

<tdcolspan='5'align='right'>

<fontstyle='font-size:8pt'><ahref='teacher.jsp?currentPage=1'>第一页a>

<%if(pd.getCurrentPage()==1){%>

<fontstyle='font-size:8pt'><ahref='teacher.jsp?currentPage=<!--d.getCurrentPage()-->'>上一页a>

<%}else{%>

<fontstyle='font-size:8pt'><ahref='teachert.jsp?currentPage=<!--d.getCurrentPage()-1-->'>上一页a>

<%}%>

<%if(pd.getCurrentPage()==pd.getPageNum(listVo)){%>

<fontstyle='font-size:8pt'><ahref='teacher.jsp?currentPage=<!--d.getCurrentPage()-->'>下一页a>

<%}else{%>

<fontstyle='font-size:8pt'><ahref='teacher.jsp?currentPage=<!--d.getCurrentPage()+1-->'>下一页a>

<%}%>

<fontstyle='font-size:8pt'><ahref='teacher.jsp?currentPage=5'>最后一页a>

<inputtype="button"value="翻到"onclick="T()"class="btn6">

<inputname="currentPage"size="3"value=<%=pd.getCurrentPage()%>>页

td>

tr>

table>

<br>

<script>

functionT(){

vari=form1.currentPage.value;

alert(i);

varj=<%=pageNum%>;

if((i>0)&&(i<j)){

window.location="teacher.jsp?currentPage="+i;

}

else{

window.location="teacher.jsp?currentPage="+j;

}

}

script>

form>

body>

 

 

 

========================================================================================================================

 

 

前言

      在使用数据库的过程中,不可避免的需要使用到分页的功能,可是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;

}  

 

/*如果要提高效率,可以利用select count(*) 语句取得所有记录数,注释掉

构造函数的rs.last();rowsCount=rs.getRow();rs.beforeFirst();三句。

在调用构造函数后调用此方法获得所有的记录,参数是select count(*)后的结果集

*/

public void setRowsCount(java.sql.ResultSet rs)throws java.sql.SQLException {

    if(rs==null) throw new SQLException("given ResultSet is NULL","user");

    rowCount=rs.getInt(1);

}

 

 

  这里只是简单的取得一个总记录数,并将记录游标移回初始位置(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,这个分页的实现是否对你的编程有帮助呢?仔细看看,其实真正自己写的代码并不多的,大部分都只是简单的转发操作。一个合适的模式应用可以帮你很大忙。

 

 

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

分享到:
评论

相关推荐

    JAVA分页大全.txt

    根据提供的文件信息,我们可以深入探讨Java分页技术的相关知识点,特别是Struts框架中的分页实现。下面将详细介绍分页的基本概念、Struts框架中的分页处理方式以及如何使用自定义的`PageController`类来实现分页功能...

    java分页工具类

    page.java java分页工具类

    java分页代码完整版

    本资源提供了一个完整的Java分页代码实现,包括注释,非常适合初学者学习和实践。 分页的核心原理是通过查询数据库时限制返回结果的数量,同时提供一个偏移量来指定从哪一条数据开始获取。在Java中,我们可以使用...

    java分页控件.rar

    Java分页控件是Java开发中常用的一种组件,主要用于在大量数据展示时提供翻页功能,提高用户体验。在Web应用中,特别是在数据密集型的应用如电商、报表系统中,分页控件扮演着至关重要的角色。它允许用户按需加载...

    java分页技巧1

    本知识点主要讲解如何在Java中实现分页功能,以"java分页技巧1"为例。 首先,我们要理解四个核心变量的作用: 1. **pageSize**: 每页显示的记录数量。这决定了用户每次请求时看到的数据量。例如,如果设置为10,则...

    Ajax实现Java分页

    在Java分页中,Ajax通过向后台发送请求获取新的分页数据,并在前端更新显示。 分页的基本流程通常包括以下步骤: 1. **前端页面设计**:创建一个包含分页导航的HTML页面,如页码链接或下拉框。页面应该有适当的...

    实用java分页标签

    Java分页标签是Java Web开发中的一个重要概念,它主要用于处理大量数据的展示,尤其是在数据库查询结果需要在网页上以多页形式呈现时。这个技术可以让用户更方便地浏览和导航大量的信息,而不会一次性加载所有数据...

    java分页组件和poolman demo

    Java分页组件是Java开发中常见的一种工具,用于在处理大量数据时,将结果集分割成多页显示,以提高用户界面的响应速度和用户体验。Oracle数据库是企业级常用的数据库系统,它支持复杂的SQL查询和大数据量的处理。在...

    JAVA分页大全(下载)

    本资源“JAVA分页大全”是一个综合性的教程,旨在帮助开发者掌握Java中的各种分页实现方式。 1. **基础概念** 分页主要是为了将大数据集分割成小块,用户可以逐页浏览,而不是一次性显示所有数据。在Java中,分页...

    java分页方法总结

    ### Java分页方法总结 #### 一、MySQL的分页技术 MySQL的分页操作相对简单,主要通过`LIMIT`语句实现。该语句允许开发者指定查询结果集中的起始位置以及返回的行数。这为实现网页上的分页功能提供了极大的便利。 ...

    java分页插件,简单实用

    Java分页插件是开发大型数据应用时必不可少的工具,它可以帮助我们有效地管理数据库查询,减少服务器负担,提高用户体验。本插件以简单实用为特点,适合初学者和经验丰富的开发者使用,允许用户根据自己的需求进行...

    java分页(三种数据库)

    本篇将详细介绍如何在SQL Server、MySQL和Oracle这三种主流数据库中实现Java分页。 一、SQL Server的Java分页 在SQL Server中,可以使用`OFFSET`和`FETCH`关键字实现分页。假设我们有一个名为`users`的表,想要...

    java分页代码下载

    虽然这里的代码示例采用的是ASP.NET的语法结构,但我们可以从中抽取出与Java分页相关的概念和技术要点,并结合Java环境进行阐述。 ### Java分页原理 分页是一种在数据量较大的情况下对数据进行分割展示的技术手段...

    java分页神器,内附案例文件

    Java分页神器通过预编译SQL语句并动态生成合适的分页参数,避免了在代码中硬编码SQL,从而降低了出错的可能性,并提高了代码的可维护性。 在实际应用中,分页神器的主要功能包括: 1. 自动计算总记录数:无需额外...

    Java分页jar包pager.jar

    Java分页jar包`pager.jar`是一个专门为Java Web应用程序提供分页功能的工具包,它极大地简化了在JSP页面中实现数据分页的过程。在Web开发中,尤其是在处理大量数据时,分页是一个必不可少的功能,它使得用户可以逐页...

    JAVA分页源代码需要可以看下

    这里的"JAVA分页源代码需要可以看下"提供了分页实现的源代码示例,我们可以深入探讨一下Java中的分页实现方法。 1. **JDBC分页** 在Java中,最基本的分页实现方式是通过JDBC直接操作SQL。通常,我们需要在SQL查询...

    java分页显示,可直接运行

    综上所述,"java分页显示"项目涵盖了Java与MySQL数据库的交互、JSP页面设计、数据传输和显示等多个核心知识点,是学习Web开发过程中一个实用的实例。通过这个项目,开发者可以深入理解Web应用的前后端协作以及数据...

    最简单的java分页,代码最少,最易懂

    本教程将详细介绍一个简单、代码量少且易于理解的Java分页实现方法。 首先,我们要理解分页的基本概念。分页通常涉及到两个关键参数:当前页数(Page Number)和每页大小(Page Size)。通过这两个参数,我们可以...

    Java分页工具。。。。。。。

    本项目提供了一个自编的Java分页工具,旨在帮助开发者更方便地实现数据的分页显示。下面将详细介绍分页的基本原理以及这个分页工具可能包含的关键功能和实现方式。 分页的基本原理: 1. **数据查询**:首先,我们...

Global site tag (gtag.js) - Google Analytics