I gruppi di risultati e le dichiarazioni JDBC devono essere chiusi separatamente anche se la connessione viene chiusa in seguito?

Si dice che sia una buona abitudine chiudere tutte le risorse JDBC dopo l’uso. Ma se ho il seguente codice, è necessario chiudere il Resultset e l’Statement?

Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = // Retrieve connection stmt = conn.prepareStatement(// Some SQL); rs = stmt.executeQuery(); } catch(Exception e) { // Error Handling } finally { try { if (rs != null) rs.close(); } catch (Exception e) {}; try { if (stmt != null) stmt.close(); } catch (Exception e) {}; try { if (conn != null) conn.close(); } catch (Exception e) {}; } 

La domanda è se la chiusura della connessione fa il lavoro o se lascia alcune risorse in uso.

Quello che hai fatto è una pratica perfetta e molto buona.

La ragione per cui dico la sua buona pratica … Ad esempio, se per qualche motivo si utilizza un tipo di database “primitivo” e si chiama connection.close() , la connessione verrà restituita al pool e al ResultSet / Statement non sarà mai chiuso e quindi ti imbatterai in molti nuovi nuovi problemi!

Quindi non puoi sempre contare su connection.close() per ripulire.

Spero che aiuti 🙂

Java 1.7 rende le nostre vite molto più semplici grazie alla dichiarazione try-with-resources .

 try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement()) { try (ResultSet resultSet = statement.executeQuery("some query")) { // Do stuff with the result set. } try (ResultSet resultSet = statement.executeQuery("some query")) { // Do more stuff with the second result set. } } 

Questa syntax è piuttosto breve ed elegante. E la connection verrà effettivamente chiusa anche quando non è ansible creare la statement .

Dal javadocs :

Quando un object Statement viene chiuso, viene chiuso anche l’object ResultSet corrente, se ne esiste uno.

Tuttavia, i javadoc non sono molto chiari sul fatto che Statement e ResultSet siano chiusi quando si chiude la Connection sottostante. Semplicemente dichiarano che chiudere una connessione:

Rilascia immediatamente il database dell’object Connection e le risorse JDBC anziché attendere che vengano rilasciati automaticamente.

A mio parere, chiudere sempre ResultSets , Statements e Connections al termine, poiché l’implementazione della close potrebbe variare tra i driver del database.

È ansible risparmiare un sacco di codice piastra di caldaia utilizzando metodi come closeQuietly in DBUtils da Apache.

Ora sto usando Oracle con Java. Ecco il mio punto di vista:

È necessario chiudere ResultSet e Statement esplicito poiché Oracle ha problemi in precedenza con l’apertura dei cursori anche dopo aver chiuso la connessione. Se non si chiude il ResultSet (cursore), verrà generato un errore come il numero massimo di cursori aperti superato .

Penso che potresti incontrare lo stesso problema con altri database che usi.

Ecco il tutorial Chiudi ResultSet al termine :

Chiudi ResultSet al termine

Chiudi object ResultSet non appena finisci di lavorare con l’object ResultSet anche se l’object Statement chiude in modo implicito l’object ResultSet quando si chiude, chiudendo ResultSet dà esplicitamente la possibilità al garbage collector di recuperare la memoria il prima ansible perché l’object ResultSet può occupare molta memoria a seconda di query.

ResultSet.close();

Se vuoi un codice più compatto, ti suggerisco di usare Apache Commons DbUtils . In questo caso:

 Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = // Retrieve connection stmt = conn.prepareStatement(// Some SQL); rs = stmt.executeQuery(); } catch(Exception e) { // Error Handling } finally { DbUtils.closeQuietly(rs); DbUtils.closeQuietly(stmt); DbUtils.closeQuietly(conn); } 

Il metodo corretto e sicuro per chiudere le risorse associate a JDBC (tratto da Come chiudere correttamente le risorse JDBC – Ogni volta ):

 Connection connection = dataSource.getConnection(); try { Statement statement = connection.createStatement(); try { ResultSet resultSet = statement.executeQuery("some query"); try { // Do stuff with the result set. } finally { resultSet.close(); } } finally { statement.close(); } } finally { connection.close(); } 

Con Java 6 form penso sia meglio verificare che sia chiuso o meno prima di chiudere (ad esempio se qualche pool di pool sfrutta la connessione in altri thread) – per esempio qualche problema di rete – la dichiarazione e lo stato dei risultati possono essere chiusi. (Non succede spesso, ma ho avuto questo problema con Oracle e DBCP). Il mio modello è per quello (nella più vecchia syntax Java) è:

  try { ... return resp; } finally { if (rs != null && !rs.isClosed()) { try { rs.close(); } catch (Exception e2) { log.warn("Cannot close resultset: " + e2.getMessage()); } } if (stmt != null && !stmt.isClosed()) { try { stmt.close(); } catch (Exception e2) { log.warn("Cannot close statement " + e2.getMessage()); } } if (con != null && !conn.isClosed()) { try { con.close(); } catch (Exception e2) { log.warn("Cannot close connection: " + e2.getMessage()); } } 

In teoria non è perfetto al 100% perché tra il controllo dello stato di chiusura e la chiusura stessa c’è un po ‘di spazio per il cambio di stato. Nel peggiore dei casi riceverai un avvertimento a lungo. – ma è minore della possibilità di cambiamento di stato nelle query di lungo periodo. Stiamo utilizzando questo modello in produzione con un carico “medio” (150 utenti simultanei) e non abbiamo avuto alcun problema con esso – quindi non visualizzare mai questo messaggio di avviso.

No non è necessario chiudere nulla MA la connessione. Le specifiche di JDBC che chiudono qualsiasi object superiore chiuderanno automaticamente gli oggetti inferiori. Chiusura della Connection chiuderà tutte le Statement che la connessione ha creato. La chiusura di qualsiasi Statement chiuderà tutti i ResultSet che sono stati creati da tale Statement . Non importa se Connection è condivisibile o meno. Anche la connessione poolable deve essere pulita prima di tornare in piscina.

Naturalmente potresti avere loop lunghi annidati sulla Connection creano molte dichiarazioni, quindi chiuderle è appropriato. Quasi mai non riesco a chiudere ResultSet , sembra eccessivo quando la chiusura Statement o della Connection li chiuderà.