2010-01-13 5 views
5

Sto cercando un modello di codice generico per gestire correttamente la transazione rispetto alla possibile eccezione. Presumo che ci sia un modello di codice comune per questo, indipendentemente dal tipo concreto di transazione con cui stiamo trattando.Qual è il modello di codice corretto per finalizzare le transazioni in Java (rollback su eccezione e commit in caso di successo)?

Ho un metodo che esegue qualcosa nella transazione e desidera rilanciare l'eccezione che può verificarsi quando si trova all'interno del blocco di codice transazionale. Ecco un esempio di tale metodo:

protected void doIt() { 
    // for JDBC connection transaction may be started automatically 
    // but assume we start it here 
    Tran tran = session.beginTran(); 
    try { 
    // here comes code that does some processing 
    // modifies some data in transaction 
    // etc. 

    // success - so commit 
    tran.commit(); 

    } catch (Exception ex) { // many different exceptions may be thrown 
          // subclass of RuntimeException, SQLException etc. 
    // error - so rollback 
    tran.rollback(); 

    // now rethrow ex 
    throw ex;    // this line causes trouble, see description below 
    }  
} 

ora - c'è compilazione errore nel metodo doIt. Deve dichiarare throws Exception ma questo non è accettabile perché il metodo doIt viene utilizzato in molti posti e l'aggiunta di throws Exception porta a successive modifiche in luoghi di utilizzo diretto e indiretto di doIt. È a causa del noto problema di progettazione della lingua Java con le eccezioni dichiarate.

Ora la domanda: come cambiare eccezione vs transazione che gestisce il codice per raggiungere il mio obiettivo - gestire correttamente transazione finalizzazione (eseguire commit o rollback in base alla condizione di successo) e rigenerare esattamente la stessa eccezione che può essere catturato nel codice transazionale bloccare.

So che potrei fare qualcosa come throw new RuntimeException(ex) ma questo genera un'eccezione di altra classe e voglio evitare tale soluzione.

risposta

7

Vorrei andare per qualcosa di simile.

protected void doIt() { 
    // for JDBC connection transaction may be started automatically 
    // but assume we start it here 
    Tran tran = session.beginTran(); 
    bool success = false; 
    try { 
    // here comes code that does some processing 
    // modifies some data in transaction 
    // etc. 

    // success - so commit 
    tran.commit(); 
    success = true; 
    } finally { 
    // error - so rollback 
    if (! success) 
     tran.rollback(); 
    }  
} 

.. o se tran ha un metodo in cui è possibile interrogare lo stato (tran.isFinished()) o qualcosa del genere, non è necessario il bool. Qualsiasi eccezione generata (ad esempio runtimeexception o errore, se non ci sono eccezioni controllate) sarà sufficiente, eseguendo il blocco finally su di esso in cima allo stack.

Se il rollback genera eccezioni, è necessario prenderle e registrarle o qualcosa del genere (un rollback non riuscito è una condizione molto seria). Ricorda di NON gettare nulla in quel caso, poiché l'eccezione che sta attualmente srotolando lo stack andrà persa.

+0

Avrete bisogno di essere a conoscenza della concorrenza - quasi tutti i sistemi transazionali sembrano finire per essere usati in un contesto concorrente, e questo codice non sembra difendere particolarmente bene ... –

+0

questo è un grande soluzione. – jspcal

+0

@Alex: che cosa ha a che fare con la concorrenza? Cosa c'è di sbagliato in questo codice considerando la concorrenza? Come "difendere"? Potresti spiegare per favore? – WildWezyr

1

Supponendo che si stia utilizzando Java 5+, il framework Spring ha una semplice annotazione (@Transactional) che è possibile utilizzare per impostare le transazioni.

questo è un frammento di ciò che l'inizio del codice si guarda come se si volesse far ritirare in qualsiasi Eccezione:

import org.springframework.transaction.annotation.Transactional; 

@Transactional(rollbackFor = Exception.class) 
protected void doIt() 

Il seguente link può aiutarti a iniziare se si desidera utilizzare questo: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html . La sezione 9.5.6 è la sezione specifica per l'utilizzo di @Transactional.

+0

Posso configurare facilmente qualsiasi tipo di transazione? Anche uno personalizzato che non è supportato da Spring? – WildWezyr

Problemi correlati