代码之家  ›  专栏  ›  技术社区  ›  Bobby

如何避免Java中的RESUTSET是关闭异常?

  •  27
  • Bobby  · 技术社区  · 15 年前

    一旦我的代码到达我的 while(rs.next()) 循环它产生 ResultSet 已关闭异常。是什么导致了这个异常,我怎样才能纠正它呢?

    编辑: 我在代码中注意到我正在嵌套 while(rs.next()) 与另一个循环 (rs2.next()) ,两个结果集来自同一个数据库,这是问题吗?

    9 回复  |  直到 7 年前
        1
  •  44
  •   Apocalisp    15 年前

    听起来您在同一个连接中执行了另一个语句,然后从第一个语句遍历结果集。如果您将两个结果集的处理嵌套在同一个数据库中,则说明您做错了什么。这些集合的组合应该在数据库端完成。

        2
  •  20
  •   rmtheis sillygoose    9 年前

    这可能是由多种原因引起的,包括您正在使用的驱动程序。

    a)某些驱动程序不允许嵌套语句。根据驱动程序是否支持JDBC3.0,您应该在创建语句对象时检查第三个参数。例如,我对火鸟的Jaybird驱动程序也有同样的问题,但是该代码对Postgres驱动程序运行良好。然后,我将第三个参数添加到createStation方法调用中,并将其设置为resultset.hold_cursors_over_commit,代码也开始为firebird正常工作。

    static void testNestedRS() throws SQLException {
    
        Connection con =null;
        try {
            // GET A CONNECTION
            con = ConexionDesdeArchivo.obtenerConexion("examen-dest");
            String sql1 = "select * from reportes_clasificacion";
    
            Statement st1 = con.createStatement(
                    ResultSet.TYPE_SCROLL_INSENSITIVE,
                    ResultSet.CONCUR_READ_ONLY, 
                    ResultSet.HOLD_CURSORS_OVER_COMMIT);
            ResultSet rs1 = null;
    
            try {
                // EXECUTE THE FIRST QRY
                rs1 = st1.executeQuery(sql1);
    
                while (rs1.next()) {
                    // THIS LINE WILL BE PRINTED JUST ONCE ON
                                        // SOME DRIVERS UNLESS YOU CREATE THE STATEMENT 
                    // WITH 3 PARAMETERS USING 
                                        // ResultSet.HOLD_CURSORS_OVER_COMMIT
                    System.out.println("ST1 Row #: " + rs1.getRow());
    
                    String sql2 = "select * from reportes";
                    Statement st2 = con.createStatement(
                            ResultSet.TYPE_SCROLL_INSENSITIVE,
                            ResultSet.CONCUR_READ_ONLY);
    
                    // EXECUTE THE SECOND QRY.  THIS CLOSES THE FIRST 
                    // ResultSet ON SOME DRIVERS WITHOUT USING 
                                        // ResultSet.HOLD_CURSORS_OVER_COMMIT
    
                    st2.executeQuery(sql2);
    
                    st2.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                rs1.close();
                st1.close();
            }
    
        } catch (SQLException e) {
    
        } finally {
            con.close();
    
        }
    
    }
    

    b)代码中可能有错误。记住,不能重用语句对象,一旦对同一语句对象重新执行查询,与该语句关联的所有打开的结果集都将关闭。确保您没有关闭该语句。

        3
  •  10
  •   job    15 年前

    此外,每个语句只能打开一个结果集。因此,如果您同时迭代两个结果集,请确保它们在不同的语句上执行。在一个语句上打开第二个结果集将隐式关闭第一个结果集。 http://java.sun.com/javase/6/docs/api/java/sql/Statement.html

        4
  •  7
  •   Mohammad Faisal Reza    9 年前

    异常说明您的结果已关闭。您应该检查您的代码并查找您发出 ResultSet.close() 打电话。也寻找 Statement.close() Connection.close() . 当然,他们中的一个以前被打过电话 rs.next() 被称为。

        5
  •  6
  •   naXa stands with Ukraine    7 年前

    你可能已经关闭了 Connection Statement 这使得 ResultSet 这将导致 结果集 也被关闭。

        6
  •  4
  •   Slartibartfast    13 年前

    正确的JDBC调用应该如下所示:

    try { 
        Connection conn;
        Statement stmt;
        ResultSet rs; 
    
        try {
            conn = DriverManager.getConnection(myUrl,"",""); 
            stmt = conn.createStatement(); 
            rs = stmt.executeQuery(myQuery); 
    
            while ( rs.next() ) { 
                // process results
            } 
    
        } catch (SqlException e) { 
            System.err.println("Got an exception! "); 
            System.err.println(e.getMessage()); 
        } finally {
            // you should release your resources here
            if (rs != null) { 
                rs.close();
            }
    
            if (stmt != null) {
                stmt.close();
            }
    
            if (conn != null) {
                conn.close();
            }
        }
    } catch (SqlException e) {
        System.err.println("Got an exception! "); 
        System.err.println(e.getMessage()); 
    }
    

    只有在从结果集得到结果之后,才能关闭连接(或语句)。最安全的方法是 finally 块。然而 close() 也会悸动 SqlException 因此另一个 try-catch 块。

        7
  •  2
  •   naXa stands with Ukraine    7 年前

    检查您是否已将执行此代码的方法声明为 static . 如果是 静止的 可能有其他线程正在重置 ResultSet .

        8
  •  1
  •   Kulbhushan Chaskar    11 年前

    我得到同样的错误,一切都是正确的,只有我使用相同的语句接口对象来执行和更新数据库。 分离后,即使用语句接口的不同对象更新和执行查询,我解决了这个错误。也就是说,Do get rid from this不要在更新和执行查询时使用相同的语句对象。

        9
  •  0
  •   Skatox    7 年前

    在运行rs.next之前,请确保已关闭所有语句和结果集。 菲纳利 保证这一点

    public boolean flowExists( Integer idStatusPrevious, Integer idStatus, Connection connection ) {
        LogUtil.logRequestMethod();
    
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = connection.prepareStatement( Constants.SCRIPT_SELECT_FIND_FLOW_STATUS_BY_STATUS );
            ps.setInt( 1, idStatusPrevious );
            ps.setInt( 2, idStatus );
    
            rs = ps.executeQuery();
    
            Long count = 0L;
    
            if ( rs != null ) {
                while ( rs.next() ) {
                    count = rs.getLong( 1 );
                    break;
                }
            }
    
            LogUtil.logSuccessMethod();
    
            return count > 0L;
        } catch ( Exception e ) {
            String errorMsg = String
                .format( Constants.ERROR_FINALIZED_METHOD, ( e.getMessage() != null ? e.getMessage() : "" ) );
            LogUtil.logError( errorMsg, e );
    
            throw new FatalException( errorMsg );
        } finally {
            rs.close();
            ps.close();
        }