2010-01-13 3 views
5

Je suis à la recherche d'un modèle de code générique pour gérer correctement la transaction en ce qui concerne l'exception possible. Je présume qu'il existe un modèle de code commun, quel que soit le type de transaction concrète que nous traitons.Quel est le modèle de code approprié pour finaliser les transactions en Java (rollback sur exception et commit en cas de succès)?

J'ai une méthode qui exécute quelque chose dans la transaction et qui veut renvoyer Exception qui peut se produire à l'intérieur du bloc de code transactionnel. Voici un exemple de cette méthode:

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

maintenant - il y a erreur de compilation dans la méthode doIt. Il doit déclarer throws Exception mais ce n'est pas acceptable parce que la méthode doIt est utilisée dans de nombreux endroits et l'ajout throws Exception conduit à des modifications ultérieures dans les lieux d'utilisation directe et indirecte de doIt. C'est à cause d'un problème connu de conception de langage Java avec des exceptions déclarées.

Maintenant, la question: comment changer exception vs code de gestion des transactions pour atteindre mon objectif - gérer correctement la finalisation de la transaction (effectuer validée ou annulée en fonction des conditions de réussite) et réémettre exactement la même exception qui peut être attrapée dans le code transactionnel bloc.

Je sais que je pourrais faire quelque chose comme throw new RuntimeException(ex) mais cela jette une exception d'autre classe et je veux éviter une telle solution.

Répondre

7

Je voudrais quelque chose comme ça.

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

.. ou si tran a une méthode où vous pouvez interroger l'état (tran.isFinished()) ou quelque chose, vous n'avez pas besoin du bool. Toute exception levée (c'est-à-dire runtimeexception ou erreur, s'il n'y a pas d'exception vérifiée) passera juste à côté, en exécutant le bloc finally sur son chemin dans la pile.

Si l'annulation renvoie des exceptions, vous devrez les saisir et log-em ou quelque chose (une restauration échouée est une condition très sérieuse). Rappelez-vous de ne PAS lancer quoi que ce soit dans ce cas, car l'exception qui est actuellement en train de dérouler la pile sera perdue.

+0

Vous devez être conscient de la simultanéité - presque tous les systèmes transactionnels semblent être utilisés dans un contexte concurrent, et ce code ne semble pas défendre particulièrement bien contre cela ... –

+0

Solution. – jspcal

+0

@Alex: qu'est-ce que cela a à voir avec la concurrence? Quel est le problème avec ce code considérant la concurrence? Comment "défendre"? Voulez-vous s'il vous plaît expliquer? – WildWezyr

1

En supposant que vous utilisez Java 5+, le framework Spring a une annotation simple (@Transactional) que vous pouvez utiliser pour configurer les transactions.

c'est un extrait de ce que le début de votre code que vous regardez comme si vous vouliez rollback sur une exception:

import org.springframework.transaction.annotation.Transactional; 

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

Le lien suivant peut vous aider à démarrer si vous voulez utiliser: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html . La section 9.5.6 est la section spécifique à l'utilisation de @Transactional.

+0

Puis-je configurer facilement n'importe quel type de transaction? Même une coutume qui n'est pas supportée par Spring? – WildWezyr

Questions connexes