web-dev-qa-db-fra.com

Comment puis-je éviter ResultSet est une exception fermée en Java?

Dès que mon code parvient à ma boucle while(rs.next()), il génère l'exception ResultSet est fermée. Quelles sont les causes de cette exception et comment puis-je y remédier?

EDIT: Je remarque dans mon code que je niche une boucle while(rs.next()) avec un autre (rs2.next()), les deux jeux de résultats provenant du même DB, est-ce un problème?

27
soldier.moth

On dirait que vous avez exécuté une autre instruction dans la même connexion avant de parcourir le jeu de résultats à partir de la première instruction. Si vous imbriquez le traitement de deux ensembles de résultats à partir de la même base de données, vous faites quelque chose de mal. La combinaison de ces ensembles doit être effectuée du côté de la base de données.

44
Apocalisp

Cela peut être dû à un certain nombre de raisons, notamment le pilote que vous utilisez.

a) Certains pilotes n'autorisent pas les instructions imbriquées. Selon si votre pilote prend en charge JDBC 3.0, vous devez vérifier le troisième paramètre lors de la création de l’objet Statement. Par exemple, j'ai eu le même problème avec le pilote JayBird de Firebird, mais le code a bien fonctionné avec le pilote postgres. Ensuite, j'ai ajouté le troisième paramètre à l'appel de la méthode createStatement et l'ai défini sur ResultSet.HOLD_CURSORS_OVER_COMMIT, et le code a également bien fonctionné pour 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) Il pourrait y avoir un bug dans votre code. N'oubliez pas que vous ne pouvez pas réutiliser l'objet Statement. Dès que vous réexécutez une requête sur le même objet statement, tous les ensembles de résultats ouverts associés à l'instruction sont fermés. Assurez-vous de ne pas fermer la déclaration.

20
Sugar

De plus, vous ne pouvez avoir qu'un seul jeu de résultats ouvert pour chaque instruction. Ainsi, si vous effectuez une itération simultanée sur deux jeux de résultats, assurez-vous qu'ils sont exécutés sur des instructions différentes. L'ouverture d'un deuxième ensemble de résultats sur une instruction ferme implicitement la première . http://Java.Sun.com/javase/6/docs/api/Java/sql/Statement.html

10
job

L'exception indique que votre résultat est fermé. Vous devez examiner votre code et rechercher tous les emplacements où vous émettez un appel ResultSet.close(). Recherchez également Statement.close() et Connection.close(). Bien sûr, l’un d’eux est appelé avant l’appel de rs.next().

7
Itay Maman

Vous avez peut-être fermé la variable Connection ou Statement qui rendait la ResultSet, ce qui entraînerait également la fermeture de la ResultSet.

6
Nathaniel Flath

Un appel jdbc correct devrait ressembler à quelque chose comme:

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

vous pouvez fermer la connexion (ou l'instruction) uniquement après avoir obtenu le résultat du jeu de résultats. Le moyen le plus sûr est de le faire dans le bloc finally. Cependant, close() pourrait également être SqlException, d’où l’autre bloc try-catch.

4
Slartibartfast

Vérifiez si vous avez déclaré la méthode où ce code est exécuté en tant que static. Si c'est static, il est possible qu'un autre thread réinitialise la ResultSet.

2
Praveen

J’ai eu la même erreur que tout était correct, mais j’utilisais le même objet d’interface d’instruction pour exécuter et mettre à jour la base de données . Après avoir séparé, par exemple, différents objets d’interface d’instruction pour la mise à jour et l’exécution de la requête, j'ai résolu cette erreur. c’est-à-dire qu’ils s’en débarrassent n’utilisent pas le même objet de déclaration pour la mise à jour et l’exécution de la requête. 

1
Kulbhushan Chaskar

assurez-vous que vous avez bien fermé toutes vos déclarations et jeux de résultats avant d’exécuter rs.next. Finaly garantit cela

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