[英]Calling PL/SQL procedure with SYS_REFCURSOR as IN parameter using JDBC
我试图理解如何调用PL / SQL过程,该过程将SYS_REFCURSOR
作为IN
参数。
考虑以下PL / SQL过程:
print_cursor_contents(myCursor SYS_REFCURSOR , row_count OUT NUMBER);
在将值绑定到IN参数时,我使用setXXX
方法?
给我一个带有单独游标记录字段的java类,因为它的成员和这个类的实例数组似乎是表示plsql CURSOR的正确方法。 当我这样做时,我得到一个SQLException:
我使用了以下set方法
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
给我一个带有单独游标记录字段的java类,因为它的成员和这个类的实例数组似乎是表示plsql CURSOR的正确方法。
我不同意。
如果您有一个存储的函数或过程,它返回一个引用游标或将一个引用游标作为一个OUT
参数,那么引用游标将作为ResultSet
从JDBC中取出。 因此,如果可以使用SYS_REFCURSOR
参数调用存储过程,我会怀疑ResultSet
是您需要传递的。
事实上,我的怀疑得到了证实。 如果你看一下Oracle对CallableStatement
的扩展, OracleCallableStatement
,它从它的超OraclePreparedStatement
继承了一个setCursor(int, ResultSet)
方法。 因此,您可以将CallableStatement
为OracleCallableStatement
,调用setCursor
方法,然后离开。
除了这种方法实际上不起作用。
如果您尝试调用setCursor
上OracleCallableStatement
,你会得到一个异常java.sql.SQLException: Unsupported feature
。
您可以尝试使用ResultSet
调用setObject
,但只会获得另一个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()
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.