it-swarm.com.de

Wie kann ich vermeiden, dass ResultSet in Java eine Ausnahme ist?

Sobald mein Code in meine while(rs.next())-Schleife gerät, erzeugt er die ResultSet-Ausnahme. Was ist die Ursache dieser Ausnahme und wie kann ich sie korrigieren?

EDIT: Ich merke in meinem Code, dass ich die while(rs.next())-Schleife mit einem anderen (rs2.next()) verschachtelte. Beide Ergebnismengen stammen aus derselben DB. Ist dies ein Problem?

27
soldier.moth

Klingt, als hätten Sie eine andere Anweisung in derselben Verbindung ausgeführt, bevor Sie die Ergebnismenge der ersten Anweisung durchlaufen haben. Wenn Sie die Verarbeitung von zwei Ergebnissätzen aus derselben Datenbank verschachteln, machen Sie etwas falsch. Die Kombination dieser Sätze sollte auf der Datenbankseite erfolgen.

44
Apocalisp

Dies kann verschiedene Ursachen haben, einschließlich des von Ihnen verwendeten Treibers.

a) Einige Treiber erlauben keine verschachtelten Anweisungen. Abhängig davon, ob Ihr Treiber JDBC 3.0 unterstützt, sollten Sie beim Erstellen des Statement-Objekts den dritten Parameter überprüfen. Ich hatte zum Beispiel das gleiche Problem mit dem JayBird-Treiber für Firebird, aber der Code funktionierte gut mit dem Postgres-Treiber. Dann fügte ich den dritten Parameter zum createStatement-Methodenaufruf hinzu und stellte ihn auf ResultSet.HOLD_CURSORS_OVER_COMMIT ein, und der Code funktionierte gut für 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) Möglicherweise enthält Ihr Code einen Fehler. Beachten Sie, dass Sie das Statement-Objekt nicht wiederverwenden können. Sobald Sie eine Abfrage für dasselbe Anweisungsobjekt erneut ausführen, werden alle mit der Anweisung verbundenen geöffneten Resultsets geschlossen. Stellen Sie sicher, dass Sie die Anweisung nicht schließen.

20
Sugar

Außerdem kann von jeder Anweisung nur eine Ergebnismenge geöffnet sein. Wenn Sie also zwei Ergebnismengen gleichzeitig durchlaufen, stellen Sie sicher, dass sie mit unterschiedlichen Anweisungen ausgeführt werden. Das Öffnen einer zweiten Ergebnismenge für eine Anweisung schließt implizit die erste. http://Java.Sun.com/javase/6/docs/api/Java/sql/Statement.html

10
job

Die Ausnahme gibt an, dass Ihr Ergebnis geschlossen ist. Sie sollten Ihren Code überprüfen und nach dem Ort suchen, an dem Sie einen ResultSet.close()-Anruf absetzen. Suchen Sie auch nach Statement.close() und Connection.close(). Sicher wird einer von ihnen aufgerufen, bevor rs.next() aufgerufen wird.

7
Itay Maman

Möglicherweise haben Sie entweder die Connection oder Statement geschlossen, die die ResultSet vorgenommen haben, was dazu führen würde, dass auch die ResultSet geschlossen wird.

6
Nathaniel Flath

Der richtige jdbc-Aufruf sollte ungefähr so ​​aussehen:

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

sie können die Verbindung (oder Anweisung) nur dann schließen, wenn Sie das Ergebnis aus der Ergebnismenge erhalten. Am sichersten ist es, dies im finally-Block zu tun. close() könnte jedoch auch SqlException sein, daher der andere try-catch-Block.

4
Slartibartfast

Prüfen Sie, ob Sie die Methode, bei der dieser Code ausgeführt wird, als static deklariert hat. Wenn es sich um static handelt, gibt es möglicherweise einen anderen Thread, der die ResultSet zurücksetzt.

2
Praveen

Ich bekam den gleichen Fehler, dass alles korrekt war. Nur das gleiche Anweisungsschnittstellenobjekt wurde zum Ausführen und Aktualisieren der Datenbank verwendet. Nach dem Trennen, d. d. h. werden Sie nicht davon befreit, verwenden Sie dasselbe Anweisungsobjekt nicht nur zum Aktualisieren und Ausführen der Abfrage. 

1

stellen Sie sicher, dass Sie alle Anweisungen und Ergebnissätze geschlossen haben, bevor Sie rs.next ausführen. Finaly garantiert das

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

Ein ResultSetClosedException kann aus zwei Gründen geworfen werden.

1.) Sie haben eine andere Verbindung zur Datenbank hergestellt, ohne alle anderen Verbindungen zu schließen.

2.) Ihr ResultSet gibt möglicherweise keine Werte zurück. Wenn Sie also versuchen, auf Daten aus dem ResultSet zuzugreifen, wird Java ein ResultSetClosedException auslösen.

0