2010-03-02 15 views
21

Quando si utilizza un PreparedStatement in JDBC, dovrei chiudere il PreparedStatement primo o il primo Connection? Ho appena visto un esempio di codice in cui il Connection viene chiuso per primo, ma a me sembra più logico chiudere prima il PreparedStatement.Chi devo prima chiudere, PreparedStatement o Connection?

Esiste un modo standard e accettato per farlo? Importa? Fa chiudere il Connection anche causare il PreparedStatement da chiudere, dal momento che la PreparedStatement è direttamente correlata all'oggetto Connection?

+1

Dove l'hai visto? – BalusC

+0

Anche se, secondo le specifiche, la dichiarazione deve essere chiusa quando la connessione è chiusa, i driver JDBC hanno riscontrato problemi con questo, quindi è considerato una buona pratica chiudere esplicitamente l'istruzione (e il set di risultati). – Yishai

+0

Chiudere le cose nell'ordine inverso in cui le hai aperte. Tutte le cose. – EJP

risposta

36

La dichiarazione. Mi aspetto di chiudere (in ordine)

  1. il set di risultati
  2. la dichiarazione
  3. la connessione

(e verificare la presenza di valori null lungo la strada!)

vale a dire chiudere in invertire ordine alla sequenza di apertura.

Se si utilizza Primavera JdbcTemplate (o simili) allora che si prenderà cura di questo per voi. In alternativa è possibile utilizzare Apache Commons DbUtils e DbUtils.close() o DbUtils.closeQuietly().

+1

Infatti. Alcuni driver JDBC generano un'eccezione alla chiusura di un set di risultati o di una dichiarazione dopo la chiusura della connessione. – Yishai

+11

Questo è corretto. Al punto: chiudere le * risorse * in ** ordine inverso ** al momento dell'acquisto. – BalusC

7

Le seguenti procedure dovrebbe essere fatto (in ordine)

  • Il ResultSet
  • Il PreparedStatement
  • Il Connection.

Inoltre, è consigliabile chiudere tutti gli oggetti relativi a JDBC nello finally nelle vicinanze per garantire la chiusura.

//Do the following when dealing with JDBC. This is how I've implemented my JDBC transactions through DAO.... 

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

try { 
    conn = .... 
    ps = conn.prepareStatement(...); 

    //Populate PreparedStatement 
    rs = ps.executeQuery(); 

} catch (/*All relevant exceptions such as SQLException*/Exception e) { 
    logger.error("Damn, stupid exception: " , e); 
} finally { 
if (rs != null) { 
      try { 
       rs.close(); 
       rs = null; 
      } catch (SQLException e) { 
       logger.error(e.getMessage(), e.fillInStackTrace()); 
      } 
     } 

     if (ps != null) { 
      try { 
       ps.close(); 
       ps = null; 
      } catch (SQLException e) { 
       logger.error(e.getMessage(), e.fillInStackTrace()); 
      } 
     } 

     try { 
      if (conn!= null && !conn.isClosed()){ 
       if (!conn.getAutoCommit()) { 
        conn.commit(); 
        conn.setAutoCommit(true); 
       } 
       conn.close(); 
       conn= null; 
      } 
     } catch (SQLException sqle) { 
      logger.error(sqle.getMessage(), sqle.fillInStackTrace()); 
     } 
} 

Potete vedere che ho controllato se i miei oggetti sono nulli e per il collegamento, controllare prima se la connessione non è autocommited. Molte persone non riescono a controllarlo e si rendono conto che la transazione non è stata impegnata in DB.

+5

Tutto questo, infine, deve essere condensato in un metodo di utilità (ad esempio 'DBUtils.close (rs, ps, conn);'). Anche il consiglio sull'autocommit dipende dalla situazione. A volte, quando c'è un'eccezione, non vuoi affatto commettere. Inoltre, lo sforzo di impostare esplicitamente il riferimento su null è quasi sempre non necessario, perché verrà cancellato quando il metodo termina, che si spera molto presto, altrimenti il ​​metodo è probabilmente troppo lungo. – Yishai

+0

@Yishai - grazie, mi stavo chiedendo. – froadie

+0

@Yishai, sì, ho dimenticato di dire che se ci sono delle eccezioni e l'autocommit è disattivato, puoi fare un rollback ... Grazie per averlo mostrato. –

Problemi correlati