SpringJDBC 調用oracle 通用存儲過程分頁

我博客前面有寫道SpringJDBC調用通用的Oracle存儲過程,今天來講一下通用的Java存儲過程帶分頁的功能,其中裏面還有動態查詢的SQL拼接,好的,先上代碼

1.Java代碼

    @Autowired
    private JdbcTemplate jdbcTemplate;


    /**分頁查詢
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/findPageList", method = {RequestMethod.GET, RequestMethod.POST}, produces = "application/json;charset=utf-8")
    public IResult findPageList(@RequestBody String param){
        HashMap hashMap = JSON.parseObject(param, HashMap.class);
        String name=(String) hashMap.get("name");
        List<String> reqList=null;
        if( hashMap.get("reqList") != null){
            reqList=(List<String>) hashMap.get("reqList");
        }
        List<String> resList=(List<String>) hashMap.get("resList");

       Map<String,Object> map=this.callPageProcedure(name,reqList,resList);
       List rlist= (List)map.get("data");
       int rtotal= (Integer)map.get("total");
       return new PageResultBean<Collection<Map>>(rlist,rtotal);

    }

    /***
     *    分頁的存儲過程
     * *  獲取數據庫內的存儲過程--返回一個Map,封裝有list集合和總記錄數
     * @param procedureName 存儲過程名
     * @param inParameter   輸入的參數page,limit 至少有2個
     * @param outParamter   輸出的參數
     * @return
     */
    private Map<String,Object> callPageProcedure(final String procedureName,final List inParameter,final List outParamter){
        if(procedureName==null || procedureName.length() == 0 ){
            return null;
        }
        //輸入參數的校驗
        if(inParameter ==null ){
            throw new BizException("輸出參數爲空!");
        }
        //輸入參數的校驗
        if(inParameter.size()<2 ){
            throw new BizException("輸出參數的個數錯誤!");
        }

        //輸出參數的校驗,沒有返回參數則拋出異常
        if(outParamter == null || outParamter.size() == 0){
          throw new BizException("輸出參數爲空!");
        }

        Map<String,Object> r = (Map<String,Object>) jdbcTemplate.execute(
                new CallableStatementCreator() {
                    public CallableStatement createCallableStatement(Connection con) throws SQLException {
                        int inSize = inParameter==null?0:inParameter.size();
                        //int outSize = outParamter==null?0:outParamter.size();
                        StringBuffer sbsql = new StringBuffer();
                        sbsql.append("{call "+procedureName).append("(");
                        //注意這裏面返回的是遊標,加1即可
                        for(int i=0;i<(inSize+1);i++){
                            if(i == 0){//必須有一個參數
                                sbsql.append("?");
                            }else{
                                sbsql.append(",?");
                            }
                        }
                        sbsql.append(")}");
                        CallableStatement cs = con.prepareCall(sbsql.toString());
                        // 設置輸入參數的值
                        if(inSize > 0 ){
                            String typeName =  null;
                            for(int i=0;i<inSize;i++){
                                typeName = inParameter.get(i).getClass().getName().toString();
                                cs.setObject(i+1, inParameter.get(i));
                            }
                        }
                        // 註冊輸出參數的類型
                        System.out.println("inSize的大小 "+inSize );
                        cs.registerOutParameter(inSize, OracleTypes.INTEGER);//取條數
                        cs.registerOutParameter(inSize+1, OracleTypes.CURSOR);//取list
                        return cs;
                    }
                }, new CallableStatementCallback<Map<String,Object> >() {
                    public Map<String,Object> doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
                        int inSize = inParameter==null?0:inParameter.size();
                        Map<String,Object> resMap=new HashMap<>();
                        List<Map> list = new ArrayList();
                        cs.execute();
                        ResultSet rs = (ResultSet) cs.getObject(inSize+1);// 獲取遊標一行的值

                        int count=(int)cs.getObject(inSize);//取條數

                        while (rs.next()) {// 轉換每行的返回值到Map中
                            Map rowMap = new HashMap();
                            for(int i=0;i<outParamter.size();i++){
                                String outP = outParamter.get(i).toString();
                                rowMap.put(outP.toLowerCase(),rs.getObject(outP.toUpperCase()) );
                            }
                            list.add(rowMap);
                        }
                        rs.close();

                        resMap.put("data",list);
                        resMap.put("total",count);
                        return resMap;
                    }

                });
        return r;

    }

2.Oracle數據庫代碼

--程序包頭
create or replace package P_findAreaPage_pak
is
type outData is ref cursor;
procedure P_findAreaPage(p_pagesize int,
                        p_startsize int,
                        jgdm varchar2,
                        ywlx varchar2,
                        jgmc varchar2,
                        xzqhname varchar2,
                        sDate varchar2,
                        eDate varchar2,
                        out_pagecount out int,--輸出參數,調用的時候隨便填寫一個整數值,詳情---請看postman傳參
                        out_datacollection out outData);
end P_findAreaPage_pak;

--程序包體
create or replace package body P_findAreaPage_pak
is
procedure P_findAreaPage(p_pagesize int,
                          p_startsize int,
                          jgdm varchar2,
                          ywlx varchar2,
                          jgmc varchar2,
                          xzqhname varchar2,
                          sDate varchar2,
                          eDate varchar2,
                          out_pagecount out int,--輸出參數,調用的時候隨便填寫一個整數值
--請看postman傳參
                          out_datacollection out outData) 
as
v_sql varchar2(3000);
v_count int;
v_upCount int;
v_lowCount int;
v_where varchar2(3000):='where 1=1';
begin
    --拼接查詢條件
       IF jgdm IS NOT NULL or jgdm <> ' ' THEN
       v_where := v_where||'  and  t0.jgdm= '''||jgdm||'''';
          END IF;
       IF ywlx IS NOT NULL or ywlx <> ' ' THEN
       v_where := v_where||'  and t0.ywlx = '''||ywlx||'''';
          END IF;
       IF jgmc IS NOT NULL or jgmc <> ' ' THEN
       v_where := v_where||'  and t0.jgmc like  ''%'||jgmc||'%''';
          END IF;
       IF xzqhname IS NOT NULL or xzqhname <> ' ' THEN
       v_where := v_where||'  and t0.xzqhname like ''%'||xzqhname||'%''';
          END IF;
       IF sDate IS NOT NULL or sDate <> ' ' THEN
       v_where := v_where|| ' and t0.bzrq >= to_date('''||sDate||''',''yyyy-mm-dd'')';
          END IF;
       IF eDate IS NOT NULL or eDate <> ' ' THEN
       v_where := v_where|| ' and  t0.bzrq <= to_date('''||eDate||''',''yyyy-mm-dd'')';
      DBMS_OUTPUT.put_line(v_where);
        END IF;
     --獲取頁面總的記錄數
    execute immediate ' select count(1)
		from  AA t0  inner JOIN BB t1 on T0.BZJGDM =T1.BZJGCODE ' || v_where into v_count;
    out_pagecount:=v_count;
    --獲取數據的上下限
    v_upCount:=p_startsize*p_pagesize;   --上限
    v_lowCount:=v_upCount-p_pagesize+1; --下限
    v_sql:='select * from (select a.*,rownum r from (select nvl(substr(T1.BZJGNAME,4),''||其它地方||'') as name,count(1) as sum
					  from  AA t0  inner JOIN BB t1 on T0.BZJGDM =T1.BZJGCODE ' || v_where ||' GROUP BY T1.BZJGNAME ORDER BY count(1) desc ) a where rownum <='||to_char(v_upCount)||') B
               where r>='||to_char(v_lowCount);
    DBMS_OUTPUT.put_line(v_sql);
    open out_datacollection for v_sql;
end p_findAreaPage;
end P_findAreaPage_pak;

注意,我這裏用到了兩張表,你們可以自行新建兩張表,將我的替換即可,附上建表語句

3.建表語句,數據你們自行插入

-- Create table
create table AA
(
  jjhydmold VARCHAR2(10),
  orgid     NUMBER(20),
  jgdm      VARCHAR2(10),
  jgmc      VARCHAR2(200),
  xzqhname  VARCHAR2(100),
  bzrq      DATE,
  bzjgdm    VARCHAR2(9),
  fddbr     VARCHAR2(200),
  zjlx      VARCHAR2(100),
  zjhm      VARCHAR2(25),
  jgdz      VARCHAR2(200),
  yzbm      VARCHAR2(10),
  dhhm      VARCHAR2(42),
  zczj      NUMBER(20,8),
  zch       VARCHAR2(65),
  pzjgmc    VARCHAR2(160),
  jyfw      VARCHAR2(2000),
  pigetime  DATE,
  ywlx      VARCHAR2(50),
  zgrs      NUMBER(20),
  rn        NUMBER
)

-- Create table
create table BB
(
  bzjgid      NUMBER(10) not null,
  bzjgname    VARCHAR2(100),
  bzjgcode    VARCHAR2(100),
  bzjgjcname  VARCHAR2(50),
  centerid    NUMBER(10),
  centername  VARCHAR2(50),
  centercode  VARCHAR2(50),
  address     VARCHAR2(150),
  tellphone   VARCHAR2(50),
  leader      VARCHAR2(50),
  mobilephone VARCHAR2(50),
  remark      VARCHAR2(500),
  coltime     DATE
)

4.Postman請求
 

//請求url(Get或Post請求)
localhost:9090/produce/findPageList

//參數JSON
{"name":"P_findAreaPage_pak.P_findAreaPage",
"reqList":[ "3", "1","","換證","武漢","","","2009-02-02",1222],
"resList":["name","sum"]
    
}

//返回JSON
{
    "code": "0000",
    "msg": "success",
    "data": [
        {
            "name": "辦證大廳",
            "sum": 158
        },
        {
            "name": "青山區",
            "sum": 7
        },
        {
            "name": "洪山區",
            "sum": 7
        }
    ],
    "count": 202
}

注意reqList最後一個參數是一個輸入輸出參數,我們這裏隨便填寫一個整數值即可,我這裏填寫的是:1222

最後,附上的Java工具類

//總共4個類

//返回結果
@Data
public class PageResultBean<T> extends AbstractResult  implements Serializable{

    private static final long serialVersionUID = 1L;

    /**
     * 分頁數據,同layui接受的參數名一樣
     * */
    private T data;

    /**
     * 記錄總數,同layui接受的參數名一樣
     * */
    private Integer count;

    public PageResultBean() {
        super();
    }

    /**
     * 構造函數
     * */
    public PageResultBean(T data,Integer count) {
        super();
        this.data = data;
        this.count = count;
    }

    /**
     * 構造函數
     * */
    public PageResultBean(IErrCode e) {
        super();
        this.msg = e.getDesc();
        this.code = e.getCode();
    }

    public PageResultBean(Throwable e) {
        super();
        this.msg = e.toString();
        this.code = SYSTEM_FAIL;
    }

    /**
     * 構造函數
     * */
    public PageResultBean(String code,String msg) {
        super();
        this.msg = msg;
        this.code = code;
    }
}

//返回結果
@Data
public abstract class AbstractResult implements IResult{
    /**成功Code*/
    public static final String SUCCESS = "0000";
    /**系統失敗Code*/
    public static final String SYSTEM_FAIL = "9999";
    /**檢查失敗Code*/
    public static final String CHECK_FAIL = "9100";
    /**業務失敗Code*/
    public static final String BIZ_FAIL = "9200";
    
    public static final String HTTP_FILE="5000";

    /**錯誤代碼*/
    protected String code = SUCCESS;
    /**錯誤信息*/
    protected String msg = "success";
}

//返回結果
public interface IResult {

}


/**
 * 業務異常封裝
 * @author leiYao 2017-11-10
 * */
@Data
public class BizException extends RuntimeException {

	private static final long serialVersionUID = 1L;

	private String errorCode;

	public BizException() {
	}

	/**
	 * 構造函數
	 * */
	public BizException(String code,String message) {
		super(message);
		this.errorCode = code;
	}

	/**
	 * 構造函數
	 * */
	public BizException(IErrCode e) {
		super(e.getDesc());
		this.errorCode = e.getCode();
	}

	public BizException(Throwable cause) {
		super(cause);
	}

	public BizException(String message, Throwable cause) {
		super(message, cause);
	}

	public BizException(String message) {
		super(message);
	}

}

 

發佈了33 篇原創文章 · 獲贊 7 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章