2010-01-23 13 views
6

Ho un'app Java che apre una connessione a un database all'inizio e la chiude alla fine. Tuttavia, il programma non finisce sempre, perché viene lanciata un'eccezione o la sto mettendo a debug e la interrompono a metà.Problema con la mancata connessione db durante il debug?

Ciò causerà l'apertura delle connessioni per accumulare e rallentare il database, oppure verrà ripulito automaticamente?

risposta

8

una connessione al database è di proprietà e gestito dal database, la classe dà solo accedi a quella risorsa del database. Se non si chiude la connessione, la classe Java potrebbe essere eliminata dal garbage collector, ma il database potrebbe non essere in grado di dire che la connessione non è più in uso e che le risorse del database potrebbero essere sprecate (fino al timeout sul lato del database) o persino perdite.

Così, quando hai finito con l'utilizzo di tuo Connection, si dovrebbe essere sicuri di chiudere in modo esplicito chiamando il suo metodo close(). Ciò consentirà al garbage collector di ricordare la memoria il prima possibile e, più importante, di rilasciare qualsiasi altra risorsa del database (cursori, maniglie, ecc.) Sulla quale la connessione potrebbe trattenere.

Il modo tradizionale di fare questo in Java è quello di chiudere il ResultSet, Statement, e Connection (in quest'ordine) in un blocco finally quando si è fatto con loro e il modello di sicurezza sembra che:

Connection conn = null; 
PreparedStatement ps = null; 
ResultSet rs = null; 

try { 
    // Do stuff 
    ... 

} catch (SQLException ex) { 
    // Exception handling stuff 
    ... 
} finally { 
    if (rs != null) { 
     try { 
      rs.close(); 
     } catch (SQLException e) { /* ignored */} 
    } 
    if (ps != null) { 
     try { 
      ps.close(); 
     } catch (SQLException e) { /* ignored */} 
    } 
    if (conn != null) { 
     try { 
      conn.close(); 
     } catch (SQLException e) { /* ignored */} 
    } 
} 

il blocco finally può essere leggermente migliorata in (per evitare il controllo nullo):

} finally { 
    try { rs.close(); } catch (Exception e) { /* ignored */ } 
    try { ps.close(); } catch (Exception e) { /* ignored */ } 
    try { conn.close(); } catch (Exception e) { /* ignored */ } 
} 

Ma, ancora, questo è estremamente dettagliato in modo generalmente finisce per utilizzare una classe di supporto per chiudere gli oggetti in metodi di supporto nulli di sicurezza e il blocco finally diventa qualcosa di simile:

} finally { 
    DbUtil.closeQuietly(rs); 
    DbUtil.closeQuietly(ps); 
    DbUtil.closeQuietly(conn); 
} 

E, in realtà, il Apache Commons DbUtils ha una classe DbUtils che sta appunto facendo che quindi non c'è bisogno di scrivi il tuo.

Nel vostro caso, questo risolverà il problema dell'eccezione, ma non quello di debug (e si sprecheranno le risorse del database fino a quando non si verificherà il timeout sul lato del database). Quindi 1. non eseguire il debug del codice utilizzando un database di produzione 2. prova ad eseguire la sessione di debug fino alla fine.

+1

I ragazzi di Sun erano INSANE quando decisero di non avere distruttori. Era molto più facile chiudere qualsiasi risorsa aperta in distruttori come in C++. Ora, guarda tutto ciò che è necessario scrivere per una piccola query di database ... Dovrebbe essere stato fatto in 3 righe di codice: connettersi a db, eseguire query, ottenere risultati. –

0

No.

Se il programma continua e le connessioni sono attive, il BD ha semplicemente rifiutato la frase.

Se qualcosa è accaduto con la connessione (ad esempio, un timeout), il BD ha chiuso la connessione e non consuma risorse.

Se la connessione è stata rilasciata e il garbage collector è stato chiamato (può essere un po 'di tempo) la connessione si chiuderà prima di essere liberata.

Se il programma termina senza chiudere la connessione, tutto il processo (sistema operativo) rilascerà le sue risorse native e, tra queste, la risorsa nativa collegata al BD (probabile un socket di rete). Il BD riceverà quindi la connessione interrotta/chiusa e rilascerà la connessione.

L'unica cosa che potrebbe accadere è che una sola esecuzione si connetterebbe molte volte al BD e farebbe molto male tenerle aperte, sfruttando tutte le connessioni disponibili. Ma non è il tuo caso, penso.

Edit: in BD generali di sono fatti bad-client-comportamento -proof

2

Ecco cosa Sun (err ... Oracle?) says:

Si raccomanda che i programmatori in modo esplicito vicino connessioni e dichiarazioni che hanno creato quando non sono più necessarie.

Un programmatore che scrive codice nel linguaggio di programmazione Java e che non utilizza risorse esterne non deve preoccuparsi della gestione della memoria. Il garbage collector rimuove automaticamente gli oggetti quando non vengono più utilizzati e libera la memoria che stavano utilizzando. Quando la memoria sta per esaurirsi, riciclerà gli oggetti scartati, rendendo disponibile la memoria attualmente occupata per un rapido riutilizzo.

Tuttavia, se un'applicazione utilizza risorse esterne, come fa quando accede a un DBMS con l'API JDBC, il garbage collector non ha modo di conoscere lo stato di tali risorse. Continuerà a riciclare gli oggetti scartati, ma se c'è molta memoria libera nell'heap Java, è possibile che i dati vengano raccolti raramente, anche se la (piccola) quantità di spazzatura Java sta mantenendo aperte grandi quantità di costose risorse di database. Pertanto, si consiglia ai programmatori di chiudere esplicitamente tutte le connessioni (con il metodo Connection.close) e le istruzioni (con il metodo Statement.close) non appena non sono più necessarie, liberando così le risorse DBMS il prima possibile. Questo vale soprattutto per le applicazioni che sono destinate a funzionare con diversi DBMS a causa di variazioni da un DBMS a un altro.

Vorrei inserire l'accesso al database in un blocco try e assicurarmi di chiudere tutte le istruzioni e le connessioni in un blocco finally.

2

Il server db avrà un'impostazione di timeout. Chiuderà la connessione e ripristinerà tutte le transazioni non vincolate. Ciò è accaduto da decenni su qualsiasi prodotto db con capacità produttiva.

Se si vuole fare è utilizzare correttamente un try {..il tuo codice ..} {connessioni ..close ..} finalmente

+0

Inoltre, la maggior parte dei protocolli DB esegue il ping dall'altro lato per vedere se è vivo. –

Problemi correlati