Oracle 分页存储过程

Posted duosl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle 分页存储过程相关的知识,希望对你有一定的参考价值。

--1、创建一个分页所用的包,定义接收结果集的游标
create or replace package pkg_fy as
 type cur_records is ref cursor;
end pkg_fy;

--2、创建一个分页的存储过程,
    --输入参数:
      --tableName 需要查询的表名
      --searchFieldSQL 需要查询的字段SQL,可以传入*
      --pageNo 当前页码
      --pageSize 每页的记录数
      --whereCase 查询所需要的条件
      --orderSQL 排序SQL
      
    --输出参数:
      --total 总记录条数
      --totalPage 总页数
      --resultSet 返回的结果集
      
    --辅助变量:
      --beginIndex -->查询的开始下标 (pageNo-1)*pageSize
      --endIndex  --> 查询的结束下标 pageNo*pageSize
      --sql1  获取总记录条数的SQL语句
      --sql2  获取要查询的页的记录的SQL语句

-----------------------创建存储过程--------------------------------
create or replace procedure p_fenye(
      tableName in varchar2, --需要查询的表名
      searchFieldSQL in varchar2, --需要查询的字段SQL,可以传入*
      pageNo in number, --当前页码
      pageSize in number, --每页的记录数
      whereCase in varchar2, --查询所需要的条件
      orderSQL in varchar2, --排序SQL
      total out number, --总记录条数
      totalPage out number, --总页数
      resultSet out pkg_fy.cur_records --返回的结果集
) is
      beginIndex number; --查询的开始下标 (pageNo-1)*pageSize
      endIndex number;  -- 查询的结束下标 pageNo*pageSize
      sql1  varchar2(1000); --获取总记录条数的SQL语句
      sql2  varchar2(2000); --获取要查询的页的记录的SQL语句
begin
  --1、获取总记录数,并保存到输出参数中
  sql1:=select count(*) from ||tableName;
  if whereCase is not null or whereCase <> ‘‘ then
    sql1:=sql1 ||  where || whereCase;
  end if;
  Execute immediate sql1 into total;--立即执行该SQL语句,将结果保存在total变量中
  
  --2、计算该页的起始下标和结束下标以及总页数
  beginIndex:=(pageNo-1)*pageSize;
  endIndex:=pageNo*pageSize;
  totalPage:=ceil(total/pagesize);
  
  --3、拼装查询语句
  sql2:=select * from (select rownum rn,t1.* from (select || searchFieldSQL || from || tableName;
      --添加where条件
  if whereCase is not null or whereCase <> ‘‘ then
    sql2:=sql2 ||  where || whereCase;
  end if;
      --添加排序
  if orderSQL is not null or orderSQL <> ‘‘ then
    sql2:=sql2 ||   || orderSQL;
  end if;
  sql2:=sql2 || ) t1 where rownum<=|| endIndex ||) t2 where rn>|| beginIndex;
  dbms_output.put_line(sql2);
  --4、将查询结果保存在游标中
  open resultSet for sql2;
end;
-----------------------创建存储过程--------------------------------

Java调用该存储过程

分页的工具实体类

/**
 * 分页实体类,用来保存查询到的数据,以及总记录数和总页数
 * @author Duosl
 *
 */
public class FenYeModel {

    private List<?> list;
    private Integer total;
    private Integer totalPage;
    public List<?> getList() {
        return list;
    }
    public void setList(List<?> list) {
        this.list = list;
    }
    public Integer getTotal() {
        return total;
    }
    public void setTotal(Integer total) {
        this.total = total;
    }
    public Integer getTotalPage() {
        return totalPage;
    }
    public void setTotalPage(Integer totalPage) {
        this.totalPage = totalPage;
    }
    
}

分页dao层代码

import java.lang.reflect.Field;
import java.math.BigDecimal;
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.Date;
import java.util.List;

public class FenYeUtil {

    // 数据库连接信息
    private static String DRIVER_CLASS = "oracle.jdbc.driver.OracleDriver";
    private static String URL = "jdbc:oracle:thin:localhost:1521/orcl?useEncoding=True&characterEncoding=utf-8";
    private static String USERNAME = "scott";
    private static String PASSWORD = "tiger";

    static Connection conn = null;
    

    public static Connection getConnection() {
        try {
            Class.forName(DRIVER_CLASS);
            conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        } catch (Exception e) {
            throw new RuntimeException("数据库连接出现错误...");
        }
        return conn;
    }

    /**
     * 分页获取表中的数据,返回ResultSet对象
     * 
     * @param clz
     *            需要将查询到的数据转换的类
     * @param tableName
     *            需要查询的表名
     * @param searchFieldSQL
     *            需要查询的字段SQL,可以传入*,例如:username,password
     * @param pageNo
     *            当前页码,即要查询的页码
     * @param pageSize
     *            每页的记录数
     * @param whereCase
     *            查询所需要的条件 例如: username=‘zhangsan‘ and password=‘m123‘
     * @param orderSQL
     *            排序SQL 例如: order by username desc
     * @return  返回一个结果集
     * @throws SQLException
     */
    public static ResultSet getRecordsByPage(String tableName, String searchFieldSQL,
            Integer pageNo, Integer pageSize, String whereCase, String orderSQL)
            throws SQLException {
        String sql = "{call p_fenye(?,?,?,?,?,?,?,?,?)}";
        conn = getConnection();
        CallableStatement cs = conn.prepareCall(sql);
        cs.setObject(1, tableName);
        cs.setObject(2, searchFieldSQL);
        cs.setObject(3, pageNo);
        cs.setObject(4, pageSize);
        cs.setObject(5, whereCase);
        cs.setObject(6, orderSQL);
        cs.registerOutParameter(7, oracle.jdbc.OracleTypes.NUMBER);
        cs.registerOutParameter(8, oracle.jdbc.OracleTypes.NUMBER);
        cs.registerOutParameter(9, oracle.jdbc.OracleTypes.CURSOR);
        
        cs.execute();
        Integer total=cs.getInt(7);
        Integer totalPage=cs.getInt(8);
        ResultSet rs = (ResultSet) cs.getObject(9);
        System.out.println("总记录数:"+total);
        System.out.println("总页数:"+totalPage);
        while (rs.next()) {
            System.out.print(rs.getObject(1)+"	");
            System.out.print(rs.getObject(2)+"	");
            System.out.print(rs.getObject(3)+"	");
            System.out.print(rs.getObject(4)+"	");
            System.out.print(rs.getObject(5)+"	");
            System.out.print(rs.getObject(6)+"	");
            System.out.println(rs.getObject(7)+"	");
        }
        System.out.println(rs);
        return rs;
    }
    
    /**
     * 分页获取表中的数据,返回上面定义的实体类对象--FenYeModel
     * 
     * @param clz
     *            需要将查询到的数据转换的类
     * @param tableName
     *            需要查询的表名
     * @param searchFieldSQL
     *            需要查询的字段SQL,可以传入*,例如:username,password
     * @param pageNo
     *            当前页码,即要查询的页码
     * @param pageSize
     *            每页的记录数
     * @param whereCase
     *            查询所需要的条件 例如: username=‘zhangsan‘ and password=‘m123‘
     * @param orderSQL
     *            排序SQL 例如: order by username desc
     * @return    返回一个工具类,包含转换后的List、总记录数和总页数
     * @throws Exception 
     */
    public static FenYeModel getRecordsByPage(Class<?> clz, String tableName, String searchFieldSQL,
            Integer pageNo, Integer pageSize, String whereCase, String orderSQL)
            throws Exception {
        String sql = "{call p_fenye(?,?,?,?,?,?,?,?,?)}";
        conn = getConnection();
        CallableStatement cs = conn.prepareCall(sql);
        cs.setObject(1, tableName);
        cs.setObject(2, searchFieldSQL);
        cs.setObject(3, pageNo);
        cs.setObject(4, pageSize);
        cs.setObject(5, whereCase);
        cs.setObject(6, orderSQL);
        cs.registerOutParameter(7, oracle.jdbc.OracleTypes.NUMBER);
        cs.registerOutParameter(8, oracle.jdbc.OracleTypes.NUMBER);
        cs.registerOutParameter(9, oracle.jdbc.OracleTypes.CURSOR);
        
        cs.execute();
        Integer total=cs.getInt(7);
        Integer totalPage=cs.getInt(8);
        ResultSet rs = (ResultSet) cs.getObject(9);
        FenYeModel model=toModelList(clz, rs);
        model.setTotal(total);
        model.setTotalPage(totalPage);
        return model;
    }
    
    /**
     * 将查询到的结果集和总记录数、总页数封装到实体类中
     * 
     * @param clz
     *            需要将查询到的数据转换的类
     * @param ResultSet
     *            查询到的结果集
     * @return
     * @throws Exception 
     */
    private static FenYeModel toModelList(Class<?> clz, ResultSet rs) throws Exception{
        FenYeModel model=new FenYeModel();
        List<Object> list = new ArrayList<Object>();
        Field[] fields = clz.getDeclaredFields();
        while (rs.next()) {
            Object obj = clz.newInstance();
            for (Field field : fields) {
                field.setAccessible(true);
                try {
                    Object obj2 = null;
                    if (rs.getObject(field.getName()) != null) {
                        if ("java.math.BigDecimal".equals(rs.getObject(field.getName()).getClass().getName())) {
                            if("java.lang.Integer".equals(field.getType().getName())){
                                obj2 = ((BigDecimal) rs.getObject(field.getName())).intValue();
                            }else if("java.lang.Double".equals(field.getType().getName())){
                                obj2 = ((BigDecimal) rs.getObject(field.getName())).doubleValue();
                            }
                            //此处可以进行其他Number类型的判断和类型转换
                        }else if("java.sql.Timestamp".equals(rs.getObject(field.getName()).getClass().getName())){
                            obj2 = (Date)rs.getObject(field.getName());
                        } else {
                            obj2 = rs.getObject(field.getName());
                        }
                        field.set(obj, obj2);
                    }
                } catch (Exception e) {
                    //测试的时候最好加上这句异常,投入使用时,可以注释掉
                    //e.printStackTrace();
                }
            }
            list.add(obj);
        }
        model.setList(list);
        return model;
    }

    //main测试
    public static void main(String[] args) throws Exception {
        FenYeModel model= getRecordsByPage(Emp.class,"emp","*",3,5,"","");
        for (Object e : model.getList()) {
            System.out.println((Emp)e);
        }
    }
}

希望可以帮助到大家!有不足还望大神指出...

最后附上源码链接https://pan.baidu.com/s/1OBTpEXC2gHAxhYLzYDTOSg

以上是关于Oracle 分页存储过程的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 分页存储过程

我的oracle分页存储过程

[转]Oracle分页之二:自定义web分页控件的封装

java调用Oracle分页存储过程

关于oracle分页顺序问题,我的代码可以实现分页,但是新添加进去的,顺序不是在最后

oracle pl/sql 分页