我博客前面有寫道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);
}
}