2009-06-01 10 views
21

Non appena il mio codice arriva al mio ciclo while(rs.next()) produce l'eccezione ResultSet chiusa. Che cosa causa questa eccezione e come posso correggerla?Come posso evitare che ResultSet sia un'eccezione chiusa in Java?

EDIT: ho notato nel mio codice che sto nidificazione while(rs.next()) ciclo con un altro (rs2.next()), entrambi i set di risultati provenienti dalla stessa DB, questo è un problema?

+5

Aggiungere un elenco del codice. – JeeBee

risposta

39

Sembra che tu abbia eseguito un'altra istruzione nella stessa connessione prima di attraversare il set di risultati dalla prima istruzione. 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.

+0

sì, quello che ho fatto, grazie per la spiegazione. –

+4

Questo non è vero per tutti i driver e RDBMS. –

+0

sqlserver.jar non può farlo nidificare, ma jtds.jar può farlo. –

6

L'eccezione indica che il risultato è stato chiuso. Dovresti esaminare il tuo codice e cercare la posizione in cui emetti una chiamata ResultSet.close(). Cerca anche Statement.close() e Connection.close(). Di sicuro, uno di loro viene chiamato prima che venga chiamato lo rs.next().

4

Potreste aver chiuso sia la Connection o Statement che ha fatto la ResultSet, che porterebbe alla ResultSet essere chiuso pure.

9

Inoltre, è possibile 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

4

chiamata JDBC corretta dovrebbe essere simile:

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

è possibile chiudere la connessione (o dichiarazione) solo dopo si ottiene il risultato di set di risultati. Il modo più sicuro è farlo nel blocco finally. Tuttavia, close() potrebbe anche essere SqlException, quindi l'altro blocco try-catch.

+1

Devi amare quel try/catch annidato. A volte odio davvero JDBC. Fa gonfiare questo esempio ma dovresti davvero chiudere anche il set di risultati e la dichiarazione. L'hai chiamata una vera chiamata JDBC! – banjollity

+0

bisogno di un controllo se rs/stmt/conn non è nullo ... –

+0

@DanielMagnusson Hai ragione. Ho risolto la risposta. – Slartibartfast

17

Questo 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'oggetto 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 errore nel codice. Ricordare che non è possibile riutilizzare l'oggetto Statement, una volta eseguita nuovamente una query sullo stesso oggetto istruzione, vengono chiusi tutti i gruppi di risultati aperti associati all'istruzione. Assicurati di non chiudere la dichiarazione.

+0

Stavo riscontrando lo stesso problema con i driver JDBC di Firebird. Posso verificare che il 'ResultSet.HOLD_CURSORS_OVER_COMMIT' funzioni. –

+0

Gli stessi problemi sui driver DB2 sono risolti con questo flag! – bobbel

2

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

1

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

Problemi correlati