2014-11-20 37 views
2

我想了解如何調用一個以SYS_REFCURSOR作爲IN參數的PL/SQL過程。用SYS_REFCURSOR作爲IN參數調用PL/SQL過程使用JDBC

考慮下面的PL/SQL程序:

print_cursor_contents(myCursor SYS_REFCURSOR , row_count OUT NUMBER); 

在結合價值做我使用的方法setXXX IN參數的時間?

給我一個帶有單獨遊標記錄字段的java類,因爲它的成員和這個類的一個實例數組似乎是表示一個plsql CURSOR的正確方法。我得到的SQLException當我這樣做:

我用下面的設置方法

  callStmt.setObject(1, curRec); 

這裏是我使用上述聲明的例外:

Exception occured in the database 
Exception message: Invalid column type 
java.sql.SQLException: Invalid column type 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8921) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8396) 
    at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9176) 
    at oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:5024) 
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:234) 
    at com.rolta.HrManager.printMaxSalAllDept(HrManager.java:1022) 
    at com.rolta.HrManager.main(HrManager.java:1116) 
Database error code: 17004 
+0

下面是直接從Java傳遞SYS_REFCURSOR而不將數據保存到數據庫的解決方案:https://stackoverflow.com/questions/45865207/create-and-pass-sys-refcursor-as-an-input-parameter-to -oracle-procedure-from-jav/45881113#45881113 – 2017-08-28 10:03:16

回答

2

給我java類帶有單獨的遊標記錄字段,因爲它的成員和該類的一個實例數組似乎是表示一個plsql CURSOR的正確方法。

我不同意。

如果您有一個存儲的函數或過程,作爲參數OUT返回引用遊標或引用遊標,引用遊標作爲ResultSet從JDBC出來。所以,如果可以用SYS_REFCURSOR參數調用存儲過程,我會懷疑你需要通過一個ResultSet

事實上,我的懷疑得到了證實。如果您看看Oracle擴展到CallableStatement,OracleCallableStatement,它從它的超級接口OraclePreparedStatement繼承setCursor(int, ResultSet)方法。因此,您可以將CallableStatement投射到OracleCallableStatement,請撥打setCursor方法,然後離開您。

除了這種方法實際上不工作。

如果您嘗試在OracleCallableStatement上撥打setCursor,您將收到一個異常java.sql.SQLException: Unsupported feature

您可以嘗試撥打setObjectResultSet,但您只會得到另一個java.sql.SQLException: Invalid column type例外。

下面是您可以運行以驗證任一情況的測試類。它調用一個存儲過程以得到一個引用遊標(和因此ResultSet),然後嘗試將其傳遞給其他:

import java.sql.*; 
import oracle.jdbc.OracleTypes; 
import oracle.jdbc.OracleCallableStatement; 

public class JavaRefCursorTest { 
    public static void main(String[] args) throws Exception { 
     Connection conn = DriverManager.getConnection(
       "jdbc:oracle:thin:@localhost:1521:XE", "user", "password"); 

     try (CallableStatement cstmt1 = conn.prepareCall(
       "{ call java_ref_curs_test.get_ref_cursor(?)}")) { 
      cstmt1.registerOutParameter(1, OracleTypes.CURSOR); 
      cstmt1.execute(); 

      try (ResultSet rSet = (ResultSet)cstmt1.getObject(1)) { 
       try (CallableStatement cstmt2 = conn.prepareCall(
         "{ call java_ref_curs_test.print_refcursor(?)}")) { 

        // Uncomment the next line to call setCursor: 
        // ((OracleCallableStatement)cstmt2).setCursor(1, rSet); 

        // Uncomment the next line to call setObject: 
        // cstmt2.setObject(1, rSet); 

        cstmt2.execute(); 
       } 
      } 
     } 
    } 
} 

(這兩個程序中java_ref_curs_test採取單一SYS_REFCURSOR參數:get_ref_cursor返回REF光標和print_refcursor需要一個作爲參數,但什麼也沒有。)

那麼,您應該使用哪一個setXXX方法?我會說他們沒有。你所要求的是不可能的。

仍然可以調用此過程,但是您必須在PL/SQL中創建引用遊標,而不是在Java中,然後將其傳遞給您的過程。

例如,我可以使用下面的PL/SQL塊調用在上面的例子中使用的兩個過程:

DECLARE 
    l_curs SYS_REFCURSOR; 
BEGIN 
    java_ref_curs_test.get_ref_cursor(l_curs); 
    java_ref_curs_test.print_refcursor(l_curs); 
END; 

你可以很容易地從JDBC運行這個命令:把它放在一個字符串,並通它到Statement.executeUpdate()

+0

我試着通過執行選擇查詢來創建一個「ResultSet」,然後將它傳遞給使用setCursor的過程。我也得到了不支持的特性sql異常。即使我正在使用最新的Oracle Jdbc jar – Chiseled 2014-11-24 17:31:08

相關問題