存儲過程返回結果集需通過 REF CURSOR,且必須定義在 Package 規範 中。本文演示 Package 創建、存儲過程開啟游標、Java 端 OracleTypes.CURSOR 註冊、ResultSet 遍歷全流程。
CREATE OR REPLACE PACKAGE testpackage AS
TYPE test_cursor IS REF CURSOR;
END testpackage;
CREATE OR REPLACE PROCEDURE testc (
p_cursor OUT testpackage.test_cursor
) IS
BEGIN
OPEN p_cursor FOR SELECT * FROM hyq.testtb;
END testc;
原理:游標是指向結果集的指針,作為 OUT 參數傳遞,由調用端獲取並遍歷。
package com.example.proc;
import java.sql.*;
import oracle.jdbc.OracleTypes; // 必須引入 Oracle 專用類型
public class CallProcRefCursor {
public static void main(String[] args) {
String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
String user = "hyq";
String pwd = "hyq";
Connection conn = null;
CallableStatement proc = null;
ResultSet rs = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, pwd);
proc = conn.prepareCall("{ call hyq.testc(?) }");
// 關鍵:註冊為 OracleTypes.CURSOR
proc.registerOutParameter(1, OracleTypes.CURSOR);
proc.execute();
// 獲取 ResultSet
rs = (ResultSet) proc.getObject(1);
while (rs.next()) {
System.out.println("<tr><td>" + rs.getString(1)
+ "</td><td>" + rs.getString(2) + "</td></tr>");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeQuietly(rs);
closeQuietly(proc);
closeQuietly(conn);
}
}
static void closeQuietly(AutoCloseable c) {
if (c != null) try { c.close(); } catch (Exception ignored) {}
}
}
ojdbc*.jar 會報 ClassNotFoundException 或 invalid column type。OracleTypes.CURSOR 而非標準 Types.OTHER。proc.getObject(1) 強轉為 ResultSet,後續按普通結果集處理。EXECUTE ON testpackage TO caller。Package 中定義多個游標類型,過程參數列表對應多個 OUT REF CURSOR,Java 端依次 registerOutParameter(i, OracleTypes.CURSOR)、getObject(i) 處理。