Cómo integrar el común de JDBC idioma de la creación o la recepción de una conexión, consultar la base de datos y, posiblemente, el procesamiento de los resultados con Java 7 automático de gestión de los recursos, el intento-con-los recursos de la declaración? (Tutorial)

Antes de Java 7, el patrón habitual era algo como esto:

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, usted puede ir para:

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

   ...
   con.commit();
}

Esto cerrará la Connection y la PreparedStatement, pero, ¿qué acerca de la reversión? No puedo agregar una captura de la cláusula que contiene la reversión, ya que la conexión sólo está disponible dentro del bloque try.

¿Todavía definir la conexión fuera del bloque try? ¿Cuál es la mejor práctica aquí, especialmente si la conexión se utiliza la agrupación?

  • Yo no uso auto-cierre en esas situaciones. Como ya indica que es solo para el cierre de los recursos. Btw: la colocación de la conexión fuera de la try... bloque no ayuda, ya que no puede deshacer después de que el bloque try como la conexión ya está cerrado.
  • Posibles duplicados de stackoverflow.com/questions/8066501/…
  • No, esto no es un duplicado. Este de aquí es acerca de la estafa.rollback().
InformationsquelleAutor TPete | 2012-02-13

3 Comentarios

  1. 39
    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
       }
    }

    De acuerdo a la documentación de oracle, usted puede combinar un try-con-recursos de bloque con regularidad un bloque try. De la OMI, el ejemplo anterior se capta la lógica correcta, que es:

    • Intento de cerrar la PreparedStatement si nada va mal
    • Si algo va mal en el interior del bloque, (no importa lo que se es) revertir la transacción actual
    • Intento de cerrar la conexión, no importa lo que
    • Si algo va mal cierre de la conexión, no se puede deshacer la transacción (ya que es un método de la conexión, que ahora está en estado indeterminado), así que no trates

    En java 6 y versiones anteriores, me gustaría hacer esto con un triple conjunto anidado de los bloques try (exterior try-finally, medio try-catch, interior try-finally). El BRAZO de la sintaxis hace que este sea más breve.

    • Su solución se deshace en SQLException, pero no en RuntimeException, Error (etc.), que es un poco de un problema. finallycódigo basado haría eso. La regla de «no coger Error» no hacer rollback opcional de la operación en caso de errores.
    • si usted quiere que, luego de la captura Throwable en lugar de SQLException. Finalmente no es el lugar correcto para deshacer una transacción, como el bloque finally se activa si o no algo va mal. Usted definitivamente no quiere deshacer cuando todo funcionaba!
    • sí, a menos que se cometen antes de abandonar el bloque try (en caso de éxito). Por supuesto, en caso de que usted tenga commit-entonces-rollback-nada y esto no es lo ideal, pero es definitivamente mejor que la falta de reversión en algunos casos. Por CIERTO, sugiero editar la respuesta, ya que es tan agradable copiar-pegar el código que se debe manejar todas las excepciones.
    • Cometer en el bloque try y a rodar de nuevo en un bloque finally no es correcto. Incluso Cuando todo funciona, se hará un extra de ida y vuelta, lo cual es un gran ineficiencia. Finalmente bloques para asegurar objetos gráficos están en un estado consistente (cierre de conexiones, declaraciones, arroyos, etc) no de tomar acciones que sólo debería ocurrir cuando se produce un error (deshacer).
    • ¿Qué pasa si el cierre automático de la PreparedStatement lanza una excepción? No se que desencadenan una innecesaria rollback?
    • Una llamada a close() lanza una SQLException «si una base de datos de acceso se produce el error» (de acuerdo a la documentación). En este caso, la transacción es, de hecho, en un estado desconocido, y una reversión es apropiado.

  2. 4

    De la OMI, declarando de Conexión y PreparedStatement fuera de try-catch es la mejor manera posible en este caso.

  3. 2

    Si desea utilizar la conexión agrupada en la transacción, se debe utilizar de esta manera:

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

    Este código de ejemplo se controla la configuración de confirmación automática de los valores.

    • Parece, podríamos simplificar un poco las cosas. ¿Por qué necesitamos un detallado control de excepciones? Podemos utilizar: try (Connection conn = source.getConnection()) { conn.setAutoCommit(false); try {...; conn.commit(); } catch (SQLException ex) { conn.rollback(); throw ex;} finally { conn.setAutoCommit(true);}}

Dejar respuesta

Please enter your comment!
Please enter your name here