【问题标题】:What does "java.sql.SQLException: Unsupported feature" mean?“java.sql.SQLException:不支持的功能”是什么意思?
【发布时间】:2015-01-22 13:11:02
【问题描述】:

我的问题与 this posta post of mine 有关。我试图在使用 JDBC 调用 PL/SQL 过程时将 RE​​F_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.jarOracle Database 11g Release 2 11.2.0.4 JDBC Drivers 下的第一个 jar)。所以我不认为它是导致问题的版本。

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

【问题讨论】:

  • 您是否在您的数据库文档中查找了错误代码17023 对应的内容?
  • 您在类路径中添加的 jdbc jar 版本
  • 已更新我的帖子以反映我正在使用的 jdbc jar 版本。
  • “不支持的功能”的哪一部分不清楚?另外 11.2.0.4 不是最新的驱动程序,最新的是 12.1.0.2。见oracle.com/technetwork/database/features/jdbc/index-091264.html
  • @MarkRotteveel 但我使用的是 oracle 11g 和 Java 1,6。这就是为什么我选择了帖子中提到的罐子。

标签: java exception jdbc oracle11g


【解决方案1】:

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

我不能说为什么在OraclePreparedStatement 中声明了setCursor() 方法。我猜这是 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();

【讨论】:

  • 所以,基本上它是 Jdbc 中的非法请求/操作。我认为当前的异常消息只是误导。
猜你喜欢
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 2014-03-08
  • 2012-11-29
  • 1970-01-01
  • 1970-01-01
  • 2020-04-04
  • 1970-01-01
相关资源
最近更新 更多