2010-08-27 18 views
6

Tutto quello che ho letto su Hibernate afferma che è necessario eseguire il rollback di una transazione e chiudere la sessione quando si verifica un errore, e non c'è di solito qualche variazione del codice seguente (tratto da documenti di Hibernate) dato a titolo di esempio:Cosa succede se non si ripristina una transazione in 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(); 
} 

Questo schema mi sembra strano per un paio di motivi. In primo luogo, sembra irragionevolmente complicato per un quadro che è generalmente orientato a rendere le cose semplici. Ancora più importante, cosa succede se il codice nel blocco try genera qualcosa di diverso da un RuntimeException? Sembra che Hibernate debba essere in grado di chiudere con garbo la sessione con una transazione aperta in quel caso, presumibilmente spostandolo indietro, ma se è vero, perché preoccuparsi di chiamare rollback?

+2

Chi ti ha detto che Hibernate rende le cose semplici? :) – skaffman

risposta

4

Hibernate può semplificare molte cose, ma la gestione delle transazioni non è molto semplice, quindi per ogni transazione devi pensare molto attentamente a ciò che desideri. L'ibernazione non può aiutarti in questo.

Se il codice nel blocco try genera qualcosa di diverso da uno RuntimeException, la transazione ovviamente non esegue il commit. Ma non esplicitamente neanche il rollback. La chiamata sess.Close nel blocco finallynon esegue il rollback della transazione. Ciò che succede dipende dal fatto che si tratti di una transazione nidificata:

  • In caso contrario, alla fine la transazione scade e si ripristina.
  • In caso affermativo, la transazione padre vedrà che una transazione secondaria non ha eseguito commit quando si impegna da sola. Ciò comporterà un rollback dell'intera transazione.
0

Ancora più importante, che cosa succede se il codice nel blocco try genera qualcosa di diverso da una RuntimeException?

Se qualsiasi altra eccezione è possibile nel blocco di codice nel blocco try a parte RuntimeException, che dovrà essere un eccezione controllata, che sarà catturato dal compilatore per sé, e si dovrebbe finire in incorporando la parte di gestione di esso nel tuo codice.

Nell'esempio fornito in questa domanda, stiamo rilevando solo RuntimeException che ritengo sia il modo corretto per codificare. In questo modo, è possibile eseguire il rollback della transazione immediatamente senza dover attendere il timeout della transazione e l'eventuale rollback. Continuando a lanciare nuovamente RuntimeException, non interrompiamo anche il flusso delle eccezioni. Questo è un modo più pulito e più esplicito di lavorare con la transazione piuttosto che lasciare che il timeout della transazione inneschi il rollback della transazione.

Ovviamente, NON dobbiamo rilevare "Eccezione" nel modo in cui RuntimeException viene catturato per ovvi motivi.

Problemi correlati