Reputation: 2300
My question is related to this post and a post of mine . I am trying to pass REF_CURSOR as an IN parameter while calling a PL/SQL procedure using JDBC. Here is my code:
public int printMaxSalAllDept()
{
Connection conn = null;
OracleCallableStatement callStmt = null;
int rowCount = -1;
try
{
// Register the Jdbc Driver
// Class.forName(JDBC_DRIVER_ORACLE);
// Create a Database connection
conn = DriverManager.getConnection(DB_URL,DB_USER,DB_PWD);
// Create a query string to get the ResultSet of your choice
String getRsQuery = "SELECT e.department_id , e.last_name , "
+ "e.salary FROM employees e , (SELECT department_id , "
+ "MAX(salary) AS maxSal FROM employees GROUP BY department_id) "
+ "m WHERE e.department_id = m.department_id "
+ "AND e.salary = m.maxSal ORDER BY e.salary";
// Create a Statement
Statement stmt = conn.createStatement();
// Execute the statement
ResultSet rs = stmt.executeQuery(getRsQuery);
// Create a SQL String
String callProc = "{ call HR.EMP_PKG.print_max_sal_all_dept(? , ?) }";
// Create a Callable Statement
callStmt = (OracleCallableStatement) conn.prepareCall(callProc);
// Bind values to the IN parameter
callStmt.setCursor(1, rs);
// callStmt.setNull(1,OracleTypes.CURSOR);
// Register OUT parameters type to the SQL type of the value returned
callStmt.registerOutParameter(2, java.sql.Types.NUMERIC);
// Execute Callable Statements
callStmt.execute();
// Retrieve value from the OUT parameters
rowCount = callStmt.getInt(0);
System.out.println("Number of rows in the cursor :" + rowCount);
}
catch (SQLException se)
{
System.out.println("Exception occured in the database");
System.out.println("Exception message: "+ se.getMessage());
System.out.println("Database error code: "+ se.getErrorCode());
se.printStackTrace();
}
finally
{
// Clean up
if(callStmt != null)
{
try
{
callStmt.close();
}
catch (SQLException se2)
{
se2.printStackTrace();
}
}
if(conn != null)
{
try
{
conn.close();
}
catch (SQLException se2)
{
se2.printStackTrace();
}
}
}
return rowCount;
}
When I run the above code I get the following exception:
Exception occured in the database
java.sql.SQLException: Unsupported feature
at oracle.jdbc.driver.OraclePreparedStatement.setCursorInternal(OraclePreparedStatement.java:5867)
at oracle.jdbc.driver.OracleCallableStatement.setCursor(OracleCallableStatement.java:5297)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setCursor(OraclePreparedStatementWrapper.java:410)
at com.rolta.HrManager.printMaxSalAllDept(HrManager.java:1038)
at com.rolta.HrManager.main(HrManager.java:1344)
Exception message: Unsupported feature
Database error code: 17023
I have seen couple of posts in this forum and others which suggests updating to the latest version of JDBC driver fixes this issue. In my case I am using the latest version of JDBC driver for Oracle ( ojdbc6.jar
the very first jar under Oracle Database 11g Release 2 11.2.0.4 JDBC Drivers) . So i don't think its the version that's causing the issue.
If what I was doing was illegal the exception message thrown would have indicated that. But here with "Unsupported Feature" message it seems like this feature is either unavailable for my database(or its version that I am using (11g) ) or for the version of the JDBC driver that I am using. Is this the right interpretation of this exception ?
Upvotes: 0
Views: 16868
Reputation: 64949
I would say that the feature is not supported in any version of the JDBC driver, and will never be supported. The version of the database in this situation is not relevant.
I can't say why there ever was a setCursor()
method declared in OraclePreparedStatement
. I would guess that it was a mistake in the design of the API. In fact, you get a deprecation warning if you compile any code that attempts to call setCursor()
:
C:\>javac -Xlint JavaRefCursorTest.java
JavaRefCursorTest.java:28: warning: [deprecation] setCursor(int,ResultSet) in OraclePreparedStatement has been deprecated
((OracleCallableStatement)cstmt2).setCursor(1, rSet);
^
1 warning
This deprecation warning suggests that Oracle are planning to remove this method in the future.
I've also run my JavaRefCursorTest
class from my answer to one of your previous questions with the Oracle 12c JDBC driver (ojdbc7.jar). The end result is only slightly different: the type of exception thrown when calling setCursor()
is java.sql.SQLFeatureNotSupportedException
instead of java.sql.SQLException
. So upgrading the JDBC driver JAR won't help.
In your case, I can't see the reason why you would want to get a ref cursor out of the database and into a JDBC ResultSet
, only to pass the same ResultSet
straight back to the database. You can call the procedure with a ref cursor directly, using a PL/SQL block such as the one below:
String plsql =
"DECLARE" +
" l_curs SYS_REFCURSOR; " +
"BEGIN" +
" OPEN l_curs FOR" +
" SELECT e.department_id , e.last_name ," +
" e.salary FROM employees e , (SELECT department_id ," +
" MAX(salary) AS maxSal FROM employees GROUP BY department_id)" +
" m WHERE e.department_id = m.department_id" +
" AND e.salary = m.maxSal ORDER BY e.salary;" +
"" +
" HR.EMP_PKG.print_max_sal_all_dept(l_curs, ?);" +
"END;"
PreparedStatement stmt = conn.prepareStatement(plsql);
stmt.registerOutParameter(1, java.sql.Types.NUMERIC);
stmt.execute();
Upvotes: 2