使用JDBC和存储过程进行Oracle数据库分页查询

    链接地址:http://www.xx566.com/detail/110.html

    孔子说的真对,逝者如斯夫,不知不觉七月就又要过去了,上个月的这时候自己还在做着类似DBA的工作,这时候可已经Android入门了,跨度太大,容易 闪了腰,及时总结很重要,今天在看Oracle存储过程的时候,想起来以前使用JDBC和存储过程进行Oracle数据库分页查询的一个例子,这里顺手总 结一下。

    首先, 我们需要在Oracle数据库写存储过程,接收三个参数:一个sql语句,一个页码,一个每页条数;返回结果:总页数和当前页Result,如下:

CREATE OR REPLACE PROCEDURE P_Pagination_Util(--存储过程分页工具
    sqlString VARCHAR2,--查询语句
    page  int,--第几页
    perPageCount int,--每页几条记录
    totalPage out SYS_REFCURSOR,--查询出的总页数
    pageResultSet out SYS_REFCURSOR--当前页查询出来的结果集
)
AS
    pageSql varchar(2000);--查询某页结果的SQL语句
BEGIN
    open totalPage for 'select count(1) total from ('||sqlString||')';--查询出总数
    pageSql := 'select * from (select rownum rn,t.* from ('||sqlString||') t where rownum<='||(page*perPageCount)||')  where rn > '||(page-1)||'*'||perPageCount;
    open pageResultSet for pageSql;
END P_Pagination_Util;

    做过开发的都知道,分页查询的使用非常的频繁,任何的分页组件都由三个重要参数组成:页码、每页条数和总记录数,其他的比如总页数和下一页、尾页等的页码都可以通过这三个参数计算得到,这里封装一个自己常用的一个分页Bean,类似谷歌分页,也是大神写的,如下:

package jdbc;
 
import java.util.List;
 
@SuppressWarnings("all")
public class PageGoogle {
    private int rowCount;// 数据库一共有多少行
    private int navCount;// 计算出一共有多少页
    private int pageSize;// 每页多少条
    private int next;// 下一页
    private int prev;// 上一页
    private int begin;// 导航起始
    private int end;// 导航结束
    private int num;// 当前页
    private int first = 1;// 第一页
    private int last;// 最后一页
    private int navNum = 1;// 有多少个导航
    private List<?> pageData;// 用于存放分页之后的数据
 
    public PageGoogle() {
    };// 无参构造函数
 
    // 构造函数,分页中最关键的三个属性(当前页、总记录数、每页数)
    public PageGoogle(int num, int rowCount, int pageSize) {
        this.rowCount = rowCount;
        this.pageSize = pageSize;
        this.navCount = (int) Math.ceil(this.rowCount * 1.0 / pageSize);
        this.last = this.navCount;
        // 限制当前页范围
        this.num = Math.max(this.first, num);
        this.num = Math.min(this.last, this.num);
        this.next = Math.min(this.last, this.num + 1);// 计算下一页
        this.prev = Math.max(this.first, this.num - 1);// 计算上一页
        this.begin = Math.max(this.num - navNum / 2, this.first);
        this.end = Math.min(this.begin + this.navNum - 1, this.last);
        if (end - begin < 9) {
            begin = Math.max(this.first, this.end - this.navNum + 1);
        }
    }
 
    Getter and Setters...
     
}

    有了分页对象,接下来就是在DAO层进行调用和结果集的封装了,如下:

package jdbc;
 
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
 
public class PaginationProcedure {
 
    /**
     * 分页查询数据
     * @param sql 
     * @param currentPage 当前页
     * @param pageSize 每页条数
     * @return
     */
    public PageGoogle findList4Page(String sql, int currentPage, int pageSize) {
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        String user = "test";
        String password = "test";
        Connection conn = null;// 数据库连接对象
        CallableStatement cs = null;// 存储过程对象
        ResultSet rs = null;// 结果集,返回分页后的数据
        ResultSet rs2 = null;// 结果集,返回查询的总行数
        Object object = null;// 需要放入list的对象
        PageGoogle page = null;// 分页对象
        int total = 0;// 记录总数
        int pagenum = 0;// 总页数
        List<Object> list = new ArrayList<Object>();
        try {
            conn = DriverManager.getConnection(url, user, password);
            ;// 建立数据库连接
            /**
             * 调用分页存储过程
             */
            cs = conn.prepareCall("call P_Pagination_Util(?,?,?,?,?)");
            cs.setString(1, sql);// 传入查询语句
            cs.setInt(2, currentPage);// 当前第几页
            cs.setInt(3, pageSize);// 当前每页多少条
            cs.registerOutParameter(4, oracle.jdbc.OracleTypes.CURSOR);// 查询出来的总数
            cs.registerOutParameter(5, oracle.jdbc.OracleTypes.CURSOR);// 当前页查询出来的结果集
            cs.execute();// 执行存储过程
            rs2 = (ResultSet) cs.getObject(4);// 查询出的总数
            while (rs2.next()) {
                total = Integer.parseInt(rs2.getString("total"));
            }
            // 以当前页码,总数据量,每页显示多少条为参数构造分页对象
            page = new PageGoogle(currentPage, total, pageSize);
            System.out.println("记录总数--->" + total);
            pagenum = (int) Math.ceil(total / pageSize) + 1;
            System.out.println("总页数--->" + pagenum);
            rs = (ResultSet) cs.getObject(5);// 获取当前页的结果集
            while (rs.next()) {
                object = new Object();
                // 读取结果集封装对象
                // ...
                list.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (cs != null) {
                    cs.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        page.setPageData(list);// 放入分页后的数据
        return page;
    }
}

    总结:在软件开发过程中, 我们经常需要分页展示数据,当然一些ORM框架都已经做了很好的封装, 但有时候正是这些封装使分页查询效率低下,这时如果在数据库使用存储过程,并使用原始的JDBC来处理数据库来分页获取数据,可能效率会提升好多,同时也 有助于我们去理解ORM框架的精髓。

你可能感兴趣的:(oracle,存储过程,jdbc,分页)