“java.sql.SQLException:Unsupported feature”是什么意思?

时间:2014-11-24 18:08:31

标签: java exception jdbc oracle11g

我的问题与this posta post of mine有关。我试图在使用JDBC调用PL / SQL过程时将REF_CURSOR作为IN参数传递。这是我的代码:

 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;
 }

当我运行上面的代码时,我得到以下异常:

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

我在这个论坛上看过几篇帖子,其他人建议更新到最新版本的JDBC驱动程序修复了这个问题。就我而言,我使用最新版本的Oracle JDBC驱动程序(ojdbc6.jar Oracle Database 11g Release 2 11.2.0.4 JDBC Drivers下的第一个jar)。所以我不认为它是导致问题的版本。

如果我所做的是非法的,抛出的异常消息就表明了这一点。 但是在“不支持的功能”消息中,似乎此功能对我的数据库(或我正在使用的版本(11g))或我正在使用的JDBC驱动程序版本不可用。这是对此例外的正确解释吗?

1 个答案:

答案 0 :(得分:1)

我想说在任何版本的JDBC驱动程序中都不支持该功能,并且永远不会支持该功能。在这种情况下,数据库的版本无关紧要。

我不能说为什么在setCursor()中声明了OraclePreparedStatement方法。我猜这是API设计中的一个错误。实际上,如果编译试图调用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

此弃用警告表明Oracle计划在将来删除此方法。

我还使用Oracle 12c JDBC驱动程序(ojdbc7.jar)从my answer to one of your previous questions运行我的JavaRefCursorTest类。最终结果只是略有不同:调用setCursor()时抛出的异常类型是java.sql.SQLFeatureNotSupportedException而不是java.sql.SQLException。因此升级JDBC驱动程序JAR无济于事。

在你的情况下,我看不出你为什么想要从数据库和JDBC ResultSet中获取引用游标的原因,只能将相同的ResultSet直接传递给数据库。您可以使用PL / SQL块直接使用引用游标调用该过程,如下所示:

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();