Java調用存儲過程
* 調用存儲過程和存儲函數前過程和函數都需要先編譯成功
* 調用存儲過程和存儲函數都是用CallableStatement
* 調用存儲過程的sql語法格式:{call <procedure-name>[(<arg1>,<arg2>,...)]}
* 調用存儲函數的sql語法格式:{?=call <procedure-name>[(<arg1>,<arg2>,...)]}
* ?:表示是返回值,且只有一個,存儲函數只能有一個返回值
測試調用存儲過程
-- 存儲過程返回多個值
-- 查詢某個員工的姓名,職位和月薪
create or replace procedure queryEmpInfo(eno in number,
pename out varchar2,
pjob out varchar2,
psal out number)
as
begin
select ename,empjob,sal into pename,pjob,psal from emp where empno = eno;
end;
如上存儲過程在Java調用時只需看創建語句就可以了,存儲函數也是一樣
@Test
public void testProcedures() {
// {call <procedure-name>[<arg1>,<arg2>,...]}
String sql = "{call queryEmpInfo(?,?,?,?)}";
Connection conn = null;
CallableStatement call = null;
try {
conn = JDBCUtils.getConnection();
call = conn.prepareCall(sql);
// 對于in參數,賦值
call.setInt(1, 7839);// 1:表示第一個?號
// 對于out參數,聲明
call.registerOutParameter(2, OracleTypes.VARCHAR);
call.registerOutParameter(3, OracleTypes.VARCHAR);
call.registerOutParameter(4, OracleTypes.NUMBER);
// 執行調用
call.execute();
// 調用完就有返回值了,取出返回值
String name = call.getString(2);
String job = call.getString(3);
double sal = call.getDouble(4);
System.out.println(name + "\t" + job + "\t" + sal);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn, call, null);
}
}
/**
* 測試調用存儲函數
* -- 存儲函數
-- 查詢某個元的年收入
create or replace function queryEmpTotalSal(eno in number)
return number -- 定義返回類型
as
-- 月薪和獎金
psal emp.sal%type;
pcomm emp.comm%type;
begin
-- 得到月薪和獎金
select sal,comm into psal,pcomm from emp where empno = eno;
-- 返回年收入
return psal * 12 + nvl(pcomm,0);-- 獎金可能為null
end;
*/
@Test
public void testFunction() {
// {?=call <procedure-name>[(<arg1>,<arg2>,...)]}
String sql = "{?=call queryEempTotalSal(?)}";
// 這里第一個 ? 就相當于 out 參數,第二個 ? 就相當于 in 參數
Connection conn = null;
CallableStatement call = null;
try {
conn = JDBCUtils.getConnection();
call = conn.prepareCall(sql);
// 對于out參數,聲明
call.registerOutParameter(1, OracleTypes.NUMBER);
// 對于in參數,賦值
call.setInt(2, 7839);
// 執行調用
call.execute();
// 取出返回結果
double totalSal = call.getDouble(1);
System.out.println("7839號員工的年收入為:" + totalSal);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn, call, null);
}
/**
測試返回一個list集合,使用cursor作為out參數
例:查詢某個部門所有員工的所有信息
*/
@Test
public void testCursor() {
// 此查詢其實就是調用存儲過程,因此語法是一樣。{call <procedure-name> [(<arg1>,<arg2>,...]}
// 但是要加上調用方法所在的包名,如下
String sql = "{call testOutByCursor.queryEmpList(?,?)}";
Connection conn = null;
CallableStatement call = null;
ResultSet resultSet = null;
try {
conn = JDBCUtils.getConnection();
call = conn.prepareCall(sql);
// 賦值,輸入查詢的部門
call.setInt(1, 10);// 查10號部門
// 申明out參數
call.registerOutParameter(2, OracleTypes.CURSOR);
// 執行
call.execute();
// 得到結果,此時要將call轉成Oracle的CallableStatement
resultSet = ((OracleCallableStatement) call).getCursor(2);
while (resultSet.next()) {
int empNo = resultSet.getInt("empno");
String name = resultSet.getString("ename");
String job = resultSet.getString("empjob");
int mgr = resultSet.getInt("mgr");
Date hireDate = resultSet.getDate("hiredate");
double sal = resultSet.getDouble("sal");
double comm = resultSet.getDouble("comm");
int deptno = resultSet.getInt("deptno");
System.err.println(empNo + " " + name + " " + job + " " + mgr
+ " " + hireDate.toString() + " " + sal + " " + comm
+ " " + deptno + " ");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUtils.release(conn, call, resultSet);
}
}