Come posso evitare che ResultSet sia un’eccezione chiusa in Java?

Appena il mio codice arriva al mio while(rs.next()) produce il ResultSet è un’eccezione chiusa. Che cosa causa questa eccezione e come posso correggerla?

EDIT: ho notato nel mio codice che sto annidando while(rs.next()) con un altro (rs2.next()) , entrambi i set di risultati provenienti dallo stesso DB, si tratta di un problema?

Sembra che tu abbia eseguito un’altra istruzione nella stessa connessione prima di attraversare il set di risultati dalla prima affermazione. Se stai annidando l’elaborazione di due set di risultati dallo stesso database, stai facendo qualcosa di sbagliato. La combinazione di questi set dovrebbe essere effettuata dal lato del database.

Ciò potrebbe essere causato da una serie di motivi, incluso il driver che si sta utilizzando.

a) Alcuni driver non consentono istruzioni nidificate. A seconda che il driver supporti JDBC 3.0, è necessario controllare il terzo parametro durante la creazione dell’object Statement. Per esempio, ho avuto lo stesso problema con il driver JayBird su Firebird, ma il codice ha funzionato bene con il driver Postgres. Poi ho aggiunto il terzo parametro alla chiamata del metodo createStatement e l’ho impostato su ResultSet.HOLD_CURSORS_OVER_COMMIT, e il codice ha iniziato a funzionare bene anche per 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) Potrebbe esserci un bug nel tuo codice. Ricordare che non è ansible riutilizzare l’object Statement, una volta eseguita nuovamente una query sullo stesso object istruzione, vengono chiusi tutti i gruppi di risultati aperti associati all’istruzione. Assicurati di non chiudere la dichiarazione.

Inoltre, è ansible avere un solo set di risultati aperto da ciascuna istruzione. Quindi, se stai ripetendo due set di risultati contemporaneamente, assicurati che vengano eseguiti su dichiarazioni diverse. L’apertura di un secondo risultato impostato su una istruzione chiuderà implicitamente la prima. http://java.sun.com/javase/6/docs/api/java/sql/Statement.html

L’eccezione indica che il risultato è stato chiuso. È necessario esaminare il codice e cercare tutte le posizioni in cui si emette una chiamata ResultSet.close() . Cerca anche Statement.close() e Connection.close() . Di sicuro, uno di loro viene chiamato prima che rs.next() venga chiamato.

È ansible che sia stata chiusa la Connection o l’ Statement che ha creato il ResultSet , il che comporterebbe la chiusura del ResultSet .

La corretta chiamata jdbc dovrebbe avere un aspetto simile a:

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

puoi chiudere la connessione (o la dichiarazione) solo dopo aver ottenuto il risultato dal set di risultati. Il modo più sicuro è farlo alla finally . Tuttavia close() potrebbe anche utilizzare SqlException , quindi l’altro blocco try-catch .

Controlla se hai dichiarato il metodo in cui questo codice è in esecuzione come static . Se è static , potrebbe esserci qualche altro thread che reimposta il ResultSet .

Ho avuto lo stesso errore tutto era corretto solo io stavo usando lo stesso object di interfaccia di istruzione per eseguire e aggiornare il database. Dopo aver separato cioè utilizzando diversi oggetti dell’interfaccia di istruzioni per l’aggiornamento e l’esecuzione della query, ho risolto questo errore. vale a dire sbarazzarsi di questo non usare lo stesso object statement per sia l’aggiornamento che l’esecuzione della query.

assicurati di aver chiuso tutte le tue statistiche e set di risultati prima di eseguire rs.next. Finalmente lo garantisce

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