JDBC 中透過 CallableStatement 呼叫 Oracle 預存函數是企業級應用常見需求。本文針對「無參數函數」與「含輸入/輸出參數函數」兩大典型場景,提供完整程式碼範例與關鍵細節說明。
CREATE OR REPLACE FUNCTION f_getstring
RETURN VARCHAR2 IS
BEGIN
RETURN 'String value';
END f_getstring;
/
Connection con = dataSource.getConnection();
CallableStatement cstmt = null;
try {
// 語法:{? = call function_name}
cstmt = con.prepareCall("{? = call f_getstring}");
// 註冊第 1 個參數為 OUT,型別 VARCHAR
cstmt.registerOutParameter(1, Types.VARCHAR);
cstmt.execute();
String strValue = cstmt.getString(1);
System.out.println("The return value is: " + strValue);
} finally {
if (cstmt != null) cstmt.close();
if (con != null) con.close();
}
CREATE OR REPLACE FUNCTION f_getinfo(p_id IN INTEGER, p_age OUT INTEGER)
RETURN VARCHAR2 IS
BEGIN
p_age := 10;
RETURN 'The age is: ' || p_id;
END f_getinfo;
/
Connection con = dataSource.getConnection();
CallableStatement cstmt = null;
try {
// 語法:{? = call function_name(?, ?)}
// 參數索引:1=回傳值, 2=IN 參數, 3=OUT 參數
cstmt = con.prepareCall("{? = call f_getinfo(?, ?)}");
cstmt.registerOutParameter(1, Types.VARCHAR); // 回傳值
cstmt.setInt(2, 11); // IN 參數
cstmt.registerOutParameter(3, Types.INTEGER); // OUT 參數
cstmt.execute();
String strValue = cstmt.getString(1);
int age = cstmt.getInt(3);
System.out.println("Return: " + strValue + ", Age: " + age);
} finally {
if (cstmt != null) cstmt.close();
if (con != null) con.close();
}
| 項目 | 說明 |
|---|---|
| 呼叫語法 | {? = call func_name(?,?)},回傳值永遠佔位置 1 |
| 參數索引 | 從 1 開始,對應 SQL 中佔位符順序 |
| IN 參數 | setXxx(index, value) |
| OUT 參數 | registerOutParameter(index, sqlType),執行後用 getXxx(index) 取值 |
| IN OUT 參數 | 先 setXxx 再 registerOutParameter,執行後同樣 getXxx |
| 資源釋放 | 務必在 finally 區塊關閉 Statement 與 Connection |
CallableStatement 用完即關,避免游標洩漏。RESULT_SET 類型回傳,可用 getObject(index) 轉 ResultSet 處理大量資料。OracleTypes.STRUCT 或 ARRAY 並轉換。