2010-01-13 6 views
5

Poszukuję ogólnego wzorca kodu, aby prawidłowo obsługiwać transakcję pod kątem możliwego wyjątku. Zakładam, że istnieje wspólny wzór kodu, bez względu na konkretny rodzaj transakcji, z którą mamy do czynienia.Jaki jest prawidłowy wzorzec kodu do sfinalizowania transakcji w języku Java (wycofanie w przypadku wyjątku i zatwierdzenie w przypadku sukcesu)?

Mam metodę, która wykonuje coś w transakcji i chce ponownie wyrzucić wyjątek, który może wystąpić, gdy wewnątrz bloku kodu transakcyjnego. Oto przykład takiej metody:

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

teraz - nie ma skompilować błąd w metodzie doIt. Musi deklarować throws Exception, ale jest to niedopuszczalne, ponieważ metoda doIt jest używana w wielu miejscach i dodanie throws Exception prowadzi do kolejnych modyfikacji w miejscach bezpośredniego i pośredniego użycia doIt. Jest to spowodowane znanym problemem projektowania języka Java z zadeklarowanymi wyjątkami.

Teraz pytanie: jak zmienić wyjątek vs transakcji przenoszenia kodu, aby osiągnąć swój cel - właściwie obsłużyć finalizację transakcji (wykonanie zobowiązania lub wycofania na podstawie stanu sukces) i przekaż dokładnie ten sam wyjątek, który może być catched w kodzie transakcyjnej blok.

Wiem, że mogłem zrobić coś takiego jak throw new RuntimeException(ex), ale to rzuca wyjątek innej klasy i chcę uniknąć takiego rozwiązania.

Odpowiedz

7

Poszedłbym na coś takiego.

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

.. czy tran ma metodę, gdzie można zapytać o status (tran.isFinished()) lub coś, nie trzeba się bool. Każdy zgłoszony wyjątek (np. Wyjątek lub błąd runtimeexception, jeśli nie ma sprawdzonych wyjątków) po prostu poleci, wykonując blok finally na jego drodze do góry.

Jeśli wycofanie rzuca wyjątki, będziesz musiał złapać te i zalogować się lub coś (nieudane wycofanie jest bardzo poważnym warunkiem). Pamiętaj, aby NIE rzucać czegokolwiek w tym przypadku, ponieważ wyjątek, który obecnie rozwija stos, zostanie utracony.

+0

Musisz być świadomy współbieżności - prawie wszystkie systemy transakcyjne wydają się być używane w kontekście współbieżnym, a ten kod nie wydaje się być szczególnie chroniony przed tym ... –

+0

to jest świetne rozwiązanie. – jspcal

+0

@Alex: co to ma wspólnego ze współbieżnością? Co jest nie tak z tym kodem, biorąc pod uwagę współbieżność? Jak "bronić"? Czy mógłbyś wyjaśnić? – WildWezyr

1

Zakładając, że korzystasz z Java 5+, framework Spring ma prostą adnotację (@Transactional), której możesz użyć do konfiguracji transakcji.

jest to fragment tego, co początek kodu wyglądasz jak gdybyś zamierzał wycofać w dowolnym wyjątek:

import org.springframework.transaction.annotation.Transactional; 

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

Poniższy link może pomóc Ci zacząć, jeśli chcesz korzystać z tego: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html . Sekcja 9.5.6 to specjalna sekcja dotycząca używania @Transactional.

+0

Czy mogę łatwo skonfigurować dowolną transakcję? Nawet niestandardowy, który nie jest wspierany przez Spring? – WildWezyr

Powiązane problemy