Как можно избежать ResultSet является закрытым исключением в Java? - PullRequest
28 голосов
/ 01 июня 2009

Как только мой код попадает в мой цикл while(rs.next()), он выдает исключение ResultSet. Что вызывает это исключение и как я могу исправить его?

РЕДАКТИРОВАТЬ: Я заметил в своем коде, что я вложил цикл while(rs.next()) с другим (rs2.next()), оба набора результатов, поступающие из одной базы данных, это проблема?

Ответы [ 10 ]

49 голосов
/ 01 июня 2009

Похоже, вы выполнили другой оператор в том же соединении, прежде чем переходить к результирующему набору из первого оператора. Если вы вкладываете обработку двух наборов результатов из одной базы данных, вы делаете что-то не так. Комбинация этих наборов должна быть сделана на стороне базы данных.

20 голосов
/ 27 июля 2009

Это может быть вызвано рядом причин, включая используемый вами драйвер.

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

    }

}

б) В вашем коде может быть ошибка. Помните, что вы не можете повторно использовать объект Statement, после повторного выполнения запроса по тому же объекту Statement все открытые наборы результатов, связанные с оператором, закрываются. Убедитесь, что вы не закрываете заявление.

10 голосов
/ 01 июня 2009

Кроме того, вы можете иметь только один набор результатов, открытый из каждого оператора. Поэтому, если вы выполняете итерацию по двум наборам результатов одновременно, убедитесь, что они выполняются для разных операторов. Открытие второго набора результатов для одного оператора неявно закроет первый. http://java.sun.com/javase/6/docs/api/java/sql/Statement.html

7 голосов
/ 01 июня 2009

Исключение гласит, что ваш результат закрыт. Вы должны проверить свой код и найти все места, где вы делаете вызов ResultSet.close(). Также ищите Statement.close() и Connection.close(). Несомненно, один из них вызывается до того, как будет вызван rs.next().

6 голосов
/ 01 июня 2009

Возможно, вы закрыли либо Connection, либо Statement, который сделал ResultSet, что также привело бы к закрытию ResultSet.

4 голосов
/ 01 июня 2009

Правильный вызов 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.

2 голосов
/ 07 июня 2012

Проверьте, объявили ли вы метод, в котором этот код выполняется, как static. Если это static, возможно, какой-то другой поток сбрасывает ResultSet.

1 голос
/ 22 января 2014

Я получил ту же ошибку, все было правильно, только я использовал тот же объект интерфейса оператора для выполнения и обновления базы данных. После разделения, т. Е. Использования различных объектов интерфейса оператора для обновления и выполнения запроса, я исправил эту ошибку. т.е. избавиться от этого не использовать один и тот же объект оператора для обновления и выполнения запроса.

0 голосов
/ 30 апреля 2019

A ResultSetClosedException может быть брошено по двум причинам.

1.) Вы открыли другое соединение с базой данных, не закрывая все остальные соединения.

2.) Ваш ResultSet может не возвращать значений. Поэтому при попытке получить доступ к данным из ResultSet Java выдаст ResultSetClosedException.

0 голосов
/ 22 марта 2018

перед запуском 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();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...