【问题标题】:Cursor is closed光标关闭
【发布时间】:2012-05-05 22:30:10
【问题描述】:

我正在使用 struts 框架。我收到“光标已关闭”错误。 我检查了我的存储过程,它在 oracle 中运行良好,但我仍然收到“光标已关闭”错误。

造成的: java.sql.SQLException:光标已关闭。 在 oracle.jdbc.driver.T4CResultSetAccessor.getCursor(T4CResultSetAccessor.java:323) 在 oracle.jdbc.driver.ResultSetAccessor.getObject(ResultSetAccessor.java:85) 在 oracle.jdbc.driver.OracleCallableStatement.getObject(OracleCallableStatement.java:1401)

您能帮我了解一下是什么原因造成的吗?

【问题讨论】:

  • 请发布您认为导致此问题的代码,以便我们查看
  • Struts 无关紧要,那是前端。后端是什么样的?
  • @SeanPatrickFloyd:后端是甲骨文
  • @ShahnwazAlam 是的,显然。但通过普通的 JDBC、MyBatic、Spring-JDBC、Hibernate、JPA (等)访问?
  • @ShahnwazAlam 啊,我们到了。现在请发布您使用休眠调用存储过程的java代码

标签: java oracle hibernate stored-procedures


【解决方案1】:

由于您没有提供代码,但根据我的假设,您通过打开它从过程中返回一个游标,但同时您可能在同一个过程中关闭游标。

PROCEDURE S_S_TEST( 
  test_OUT OUT OAS_TYPES.REFCURSOR
) 
AS
BEGIN
  OPEN test_OUT FOR      
      SELECT *
      FROM table_p;
   CLOSE test_OUT;
END S_S_TEST;

调用存储过程的客户端负责关闭游标。请删除代码:CLOSE test_OUT;

参考:Cursor is Closed

【讨论】:

    【解决方案2】:

    下面的问题会来的一些时间

    例如:

    while (rs.next()) {
    
    
                registartionServices.add(new RegistrationServices(rs.getString(1), rs.getString(2), rs.getString(3),
                        rs.getString(4), rs.getString(5), rs.getString(7), rs.getString(6), rs.getString(9)));
                noti[i] rs.getString(1);
                //System.out.println("amountList-" + rs.getString(7));
                //amountList.add(rs.getString(7));
                //serviceList.add(rs.getString(6));
                //serviceListAR.add(rs.getString(6));
                i++;
            }
    

    在上面的例子中 (rs.getString(1) ) 尝试访问两次。

    而不是将 (rs.getString(1)) 分配给一个变量并使用该值。

    例如:

    while (rs.next()) {
                    notid=rs.getString(1);
                    registartionServices.add(new RegistrationServices(notid, rs.getString(2), rs.getString(3),
                            rs.getString(4), rs.getString(5), rs.getString(7), rs.getString(6), rs.getString(9)));
                    noti[i] =notid;
                    //System.out.println("amountList-" + rs.getString(7));
                    //amountList.add(rs.getString(7));
                    //serviceList.add(rs.getString(6));
                    //serviceListAR.add(rs.getString(6));
                    i++;
                }
    

    希望你得到答案。

    【讨论】:

      【解决方案3】:

      最初,REF_CURSOR 处于关闭状态,直到您打开特定 SQL 查询的游标。当您在打开游标之前由于某些条件而从未打开过游标时,您可能会收到此Cursor is closed SQL 错误。如果不满足该条件,则如果您不故意为某些虚拟值打开游标,则游标将永远不会打开。下面是一个例子:

      IF condition = TRUE THEN
          OPEN CURSOR cursor_name FOR
          SELECT * FROM table_name;
      END IF;
      

      但在这里,条件是 FALSE。因此,该过程返回一个未打开的游标。在这种情况下,我更喜欢从调用程序中捕获这个特定的异常。例如,以下是捕获特定类型异常并保持沉默的 Java 代码。

      try
      {
          cursor = (ResultSet) stmt.getObject(x);
      }
      catch(SQLException e)
      {
          if (!e.getMessage().toLowerCase().contains("cursor is closed")) {
              e.printStackTrace();
          }
      }
      

      而不是做

      try
      {
          cursor = (ResultSet) stmt.getObject(x);
      }
      catch(SQLException e)
      {
          e.printStackTrace();
      }
      

      【讨论】:

        【解决方案4】:

        希望您可以将过程输出参数作为光标返回到调用位置,但您可能会错过在过程中打开/添加输出参数光标(OPEN RESULT FOR SELECT * FROM TABLE_NAME)。

        Example:
        PROCEDURE TEST(RESULT OUT SYS_REFCURSOR) 
        AS
        BEGIN
          --your all codes
          OPEN RESULT FOR  SELECT * FROM TABLE_NAME;
        END TEST;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多