2010-08-27 25 views
6

Todo lo que leo acerca de hibernación indica que debe deshacer una transacción y cerrar la sesión cuando se produce un error, y por lo general hay una cierta variación del código siguiente (tomado de documentos de Hibernate) dada como un ejemplo:¿Qué sucede si no revierte una transacción en Hibernate?

Session sess = factory.openSession(); 
Transaction tx = null; 
try { 
    tx = sess.beginTransaction(); 
    // do some work 
    ... 
    tx.commit(); 
} catch (RuntimeException e) { 
    if (tx != null) tx.rollback(); 
    throw e; // or display error message 
} finally { 
    sess.close(); 
} 

Este patrón me parece extraño por un par de razones. Primero, parece irrazonablemente complicado para un marco que generalmente está orientado a simplificar las cosas. Más importante aún, ¿qué sucede si el código en el bloque try arroja algo más que un RuntimeException? Parece que Hibernate debe poder cerrar con gracia la sesión con una transacción abierta en ese caso, presumiblemente volviéndolo hacia atrás, pero si eso es cierto, ¿por qué molestarse en llamar al rollback?

+2

¿Quién le dijo que Hibernate hace las cosas simples? :) – skaffman

Respuesta

4

Hibernate puede simplificar muchas cosas, pero la gestión de transacciones no es muy simple, por lo que para cada transacción debe pensar cuidadosamente qué es lo que desea. Hibernate no puede ayudarte con eso.

Si el código en el bloque try arroja algo más que un RuntimeException, su transacción, obviamente, no confirma. Pero tampoco reversas explícitamente. La llamada sess.Close en su finally bloque no retrotraer la transacción tampoco. Lo que sucede depende de si se trata de una transacción anidada:

  • Si no lo es, la transacción termina y se retrotrae.
  • Si lo es, la transacción principal verá que una transacción hija no se ha comprometido cuando se confirma. Esto dará como resultado una reversión de la transacción completa.
0

Más importante aún, ¿qué sucede si el código en el bloque try lanza algo más que un RuntimeException?

Si cualquier otra excepción es posible en el bloque de código en el bloque try, aparte de RuntimeException, que tiene que ser una excepción comprobada, que podrá capturarse por el propio compilador, y que terminaría en la incorporación la parte de manejo de ella en tu código.

En el ejemplo provisto en esta pregunta, estamos captando solo RuntimeException que creo que es la manera correcta de codificar. Al hacer esto, podemos deshacer la transacción de inmediato sin tener que esperar un tiempo de espera de la transacción y una reversión final. A medida que continuamos volviendo a lanzar RuntimeException, no estamos rompiendo el flujo de excepción también. Esta es una forma más clara y más explícita de trabajar con la transacción que dejar que el tiempo de espera de la transacción desencadene la reversión de la transacción.

Por supuesto, NO debemos atrapar 'Excepción' en la forma en que se atrapa RuntimeException por razones obvias.

Cuestiones relacionadas