如何避免 Java 中的 ResultSet is closed 异常?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/935511/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:17:05  来源:igfitidea点击:

How can I avoid ResultSet is closed exception in Java?

javasqlexception

提问by soldier.moth

As soon as my code gets to my while(rs.next())loop it produces the ResultSetis closed exception. What causes this exception and how can I correct for it?

一旦我的代码进入我的while(rs.next())循环,它就会产生ResultSetis closed 异常。是什么导致了这个异常,我该如何纠正它?

EDIT:I notice in my code that I am nesting while(rs.next())loop with another (rs2.next()), both result sets coming from the same DB, is this an issue?

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

采纳答案by Apocalisp

Sounds like you executed another statement in the same connection before traversing the result set from the first statement. If you're nesting the processing of two result sets from the same database, you're doing something wrong. The combination of those sets should be done on the database side.

听起来您在遍历第一条语句的结果集之前在同一连接中执行了另一条语句。如果您嵌套处理来自同一数据库的两个结果集,那么您就做错了。这些集合的组合应该在数据库端完成。

回答by Itay Maman

The exception states that your result is closed. You should examine your code and look for all location where you issue a ResultSet.close()call. Also look for Statement.close()and Connection.close(). For sure, one of them gets called before rs.next()is called.

异常表明您的结果已关闭。您应该检查您的代码并查找您发出ResultSet.close()呼叫的所有位置。还要寻找Statement.close()Connection.close()。当然,其中一个在被调用之前rs.next()被调用。

回答by Nathaniel Flath

You may have closed either the Connectionor Statementthat made the ResultSet, which would lead to the ResultSetbeing closed as well.

您可能已经关闭了Connection或关闭StatementResultSet,这也会导致ResultSet被关闭。

回答by job

Also, you can only have one result set open from each statement. So if you are iterating through two result sets at the same time, make sure they are executed on different statements. Opening a second result set on one statement will implicitly close the first. http://java.sun.com/javase/6/docs/api/java/sql/Statement.html

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

回答by Slartibartfast

Proper jdbc call should look something like:

正确的 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()); 
}

you can close connection (or statement) only after you get result from result set. Safest way is to do it in finallyblock. However close()could also throe SqlException, hence the other try-catchblock.

只有在从结果集中获得结果后,您才能关闭连接(或语句)。最安全的方法是在finally块中进行。然而close(),也可能 throe SqlException,因此另一个try-catch块。

回答by Sugar

This could be caused by a number of reasons, including the driver you are using.

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

a) Some drivers do not allow nested statements. Depending if your driver supports JDBC 3.0 you should check the third parameter when creating the Statement object. For instance, I had the same problem with the JayBird driver to Firebird, but the code worked fine with the postgres driver. Then I added the third parameter to the createStatement method call and set it to ResultSet.HOLD_CURSORS_OVER_COMMIT, and the code started working fine for Firebird too.

a) 有些驱动程序不允许嵌套语句。根据您的驱动程序是否支持 JDBC 3.0,您应该在创建 Statement 对象时检查第三个参数。例如,我在使用 JayBird 驱动程序到 Firebird 时遇到了同样的问题,但是代码与 postgres 驱动程序一起工作得很好。然后我将第三个参数添加到 createStatement 方法调用并将其设置为 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) There could be a bug in your code. Remember that you cannot reuse the Statement object, once you re-execute a query on the same statement object, all the opened resultsets associated with the statement are closed. Make sure you are not closing the statement.

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

回答by Praveen

Check whether you have declared the method where this code is executing as static. If it is staticthere may be some other thread resetting the ResultSet.

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

回答by Kulbhushan Chaskar

I got same error everything was correct only i was using same statement interface object to execute and update the database. After separating i.e. using different objects of statement interface for updating and executing query i resolved this error. i.e. do get rid from this do not use same statement object for both updating and executing the query.

我遇到了同样的错误,一切都是正确的,只是我使用相同的语句接口对象来执行和更新数据库。在分离 ie 使用不同的语句接口对象来更新和执行查询后,我解决了这个错误。即摆脱这种不使用相同的语句对象来更新和执行查询。

回答by Renato Vasconcellos

make sure you have closed all your statments and resultsets before running rs.next. Finalyguarantees this

确保在运行 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();
    }

回答by Michael Cenzoprano

A ResultSetClosedExceptioncould be thrown for two reasons.

ResultSetClosedException两个原因可能会抛出A。

1.) You have opened another connection to the database without closing all other connections.

1.) 您在没有关闭所有其他连接的情况下打开了另一个与数据库的连接。

2.) Your ResultSet may be returning no values. So when you try to access data from the ResultSet java will throw a ResultSetClosedException.

2.) 您的 ResultSet 可能没有返回任何值。因此,当您尝试从 ResultSet 访问数据时,java 会抛出一个ResultSetClosedException.