JDBC di gestione automatica delle risorse Java 7 (istruzione try-with-resources)

Come integrare l’idioma JDBC comune di creare / ricevere una connessione, interrogare il database ed eventualmente elaborare i risultati con la gestione automatica delle risorse di Java 7, l’istruzione try-with-resources? ( Tutorial )

Prima di Java 7, il solito schema era qualcosa del genere:

Connection con = null; PreparedStatement prep = null; try{ con = getConnection(); prep = prep.prepareStatement("Update ..."); ... con.commit(); } catch (SQLException e){ con.rollback(); throw e; } finally{ if (prep != null) prep.close(); if (con != null) con.close(); } 

Con Java 7 puoi scegliere:

 try(Connection con = getConnection(); PreparedStatement prep = con.prepareConnection("Update ..."){ ... con.commit(); } 

Questo chiuderà Connection e PreparedStatement , ma per quanto riguarda il rollback? Non riesco ad aggiungere una clausola catch che contiene il rollback, perché la connessione è disponibile solo all’interno del blocco try.

Definisci ancora la connessione al di fuori del blocco try? Qual è la migliore pratica qui, soprattutto se viene utilizzato il pool di connessioni?

     try(Connection con = getConnection()) { try (PreparedStatement prep = con.prepareConnection("Update ...")) { //prep.doSomething(); //... //etc con.commit(); } catch (SQLException e) { //any other actions necessary on failure con.rollback(); //consider a re-throw, throwing a wrapping exception, etc } } 

    Secondo la documentazione di Oracle , è ansible combinare un blocco try-with-resources con un blocco try normale. IMO, l’esempio sopra riportato cattura la logica corretta, che è:

    • Tentare di chiudere il PreparedStatement se nulla va storto
    • Se qualcosa va storto nel blocco interno, (indipendentemente dal fatto), ripristina la transazione corrente
    • Tentativo di chiudere la connessione, non importa cosa
    • Se qualcosa va storto chiudendo la connessione, non è ansible eseguire il rollback della transazione (poiché si tratta di un metodo sulla connessione, che ora si trova in uno stato indeterminato), quindi non provare

    In java 6 e precedenti, lo farei con un insieme di blocchi di prova annidati (try-finally esterno, try-catch medio, try-finally interno). La syntax ARM fa questo terser.

    IMO, dichiarando che Connection e PreparedStatement al di fuori del try-catch è il modo migliore disponibile in questo caso.

    Se si desidera utilizzare la connessione in pool nella transazione, è necessario utilizzarlo in questo modo:

     try (Connection conn = source.getConnection()) { conn.setAutoCommit(false); SQLException savedException = null; try { // Do things with connection in transaction here... conn.commit(); } catch (SQLException ex) { savedException = ex; conn.rollback(); } finally { conn.setAutoCommit(true); if(savedException != null) { throw savedException; } } } catch (SQLException ex1) { throw new DataManagerException(ex1); } 

    Questo codice di esempio gestisce l’impostazione dei valori di autocommit.