2010-08-26 15 views
7

Używam zarządzania transakcjami przy użyciu Spring i Hibernate. Moja sytuacja jest następująca:
Mam fasoli który jest sorrounded przez transakcję i zadzwonić fasola B który jest zdefiniowany z transakcji w tym atrybucie „PROPAGATION_REQUIRED”Problem propagacji Spring Transaction

B w tym przypadku robi” t otworzyć nową transakcję, ale korzysta z istniejącej (patrz w dziennikach: "Uczestnictwo w istniejącej transakcji"). Jednak w przypadku, gdy metoda w B wyrzuci wyjątek runtimeException, w drodze powrotnej do A zmyje transakcję i spowoduje jej zaznaczenie do wycofania, nawet jeśli zewnętrzna metoda A złapie wyjątek i nie będzie wyrzuć to. Myślę, że to zachowanie jest złe, w tym przypadku chcę, aby A kontrolował transakcję, a B nie powinien w żadnym wypadku przerywać transakcji.
Czy istnieje sposób zdefiniowania B, aby otworzyć transakcję, jeśli nie została zdefiniowana żadna transakcja, ale DO NOTHING, jeśli jest już zawarta w transakcji exising i pozwolić wyższemu poziomowi podjąć decyzję o zatwierdzeniu lub wycofaniu?

Zobacz więcej odpowiedzi na ten temat w wątku w społeczności wiosennej here.

Odpowiedz

1

Teoretycznie jest to możliwe, ale nie mieści się w standardowych aspektach Wiosennej Transakcji. Będziesz musiał stworzyć własny aspekt, który powiela standardową funkcję sprężyny, rozszerzając ją o specjalny przypadek. Być może nawet będzie możliwe rozszerzenie oryginalnego aspektu, którego używają.

(. Prawdopodobnie trzeba będzie zdefiniować niestandardowy adnotacji jednak, bo nie można zastąpić atrybut @Transactional ani rozszerzyć enum propagacji)

Oto kilka wskazówek:

Należy również rozważyć przeczytanie książki AspectJ in Action, nawet jeśli po prostu chcesz użyć Spring AOP, ponieważ daje bardzo dobry przegląd.

Dobrym punktem wyjścia jest pobranie sources of the spring-aspects jar, zobaczyć, co robią tam i podać własne rozszerzenie obu org.springframework.transaction.aspectj.AbstractTransactionAspect lub org.springframework.transaction.aspectj.AnnotationTransactionAspect

Podsumowując: jestem pewien, że można to zrobić, ale to zajmie dużo pracy. Wiosenny interfejs API transakcji jest całkiem niezły. Może powinieneś nauczyć się żyć z jego ograniczeniami. Jeśli nie: rozpocznij hakowanie (patrz wyżej):

+0

Mówi Pan, że nie ma na to rozwiązania w postaci gotowej do użycia. Nadal będę starał się znaleźć bardziej ogólne rozwiązanie, które wymaga mniej pracy, zanim oznaczysz tę odpowiedź jako najlepszą. – Spiderman

+0

z pewnością nie ma potrzeby wybierania poprawnej odpowiedzi w ciągu godziny od pytania. Ale program byłby miły :-) –

+0

Aby zamknąć tę sprawę, myślę, że żadne obejście nie pasuje do moich żądań. Dlatego też takie zachowanie według projektu wiosny wydaje mi się ograniczeniem. Jedynym realnym rozwiązaniem jest zastąpienie wiosennej implmentacji zgodnie z sugestią. – Spiderman

0

Może za pomocą adnotacji @Transactional w sposób pokazany poniżej rozwiążesz problem? @ Transakcja (propagacja = Propagacja.REQUIRED, noRollbackFor = RuntimeException.class)

+0

nie jest dobre, ponieważ w przypadku, gdy B zostanie wywołany NIE z A, ale z innego miejsca na zewnątrz, chcę, aby wywołanie metody B było opakowane z transakcją i że w przypadku wyjątku runtimeException wykona ona wycofanie. – Spiderman

+0

@Spiderman: Dlaczego nie używać dwóch punktów wejściowych dla swojej logiki: pierwsza do wywołania z komponentu bean 'A' (' @Transactional (propagacja = ..., noRollbackFor = ...) void myMethodSafe() ') i druga jeden do wywołania z dowolnego innego miejsca ('@ Transactional (propagacja = ...) void myMethod()'). Tak, dwie metody w interfejsie, dlaczego nie?Alternatywnie możesz mieć jedną metodę interfejsu i dodatkową flagę 'boolean noRollbackForException', która jest ustawiona na 'true' gdy metoda jest wywoływana z komponentu bean' A', a następnie 'try/catch' niezbędnego wyjątku (gdy jest ustawiony na' false' wyjątek jest rzucany dalej). –

0

Jednym z rozwiązań jest podanie DWÓCH definicji fasoli w pliku context.xml.

  • Jeden z PROPAGATION_REQUIRED który będzie używany, gdy chcesz fasoli być transakcyjny sama

  • Drugi z PROPAGATION_SUPPORTS który będzie używany podczas rozmowy fasoli od wewnątrz istniejącej transakcji (Właściwie to może nawet być nietransakcyjne).

Jeśli chcesz zminimalizować duplikację, możesz uwzględnić typową konfigurację w definicji komponentu.

4

Wygląda Propagation.NESTED jest coś, co może pomóc:

  • Jeśli B nie, transakcja rozpoczął A (i nadal z B) będzie poprawnie rolledback do punktu zapisu przed B nazywa bez dotykania A.
  • Po zatwierdzeniu B, tylko punkt zapisu zostaje zwolniony, nic innego nie jest wydawane do DB. Zasadniczo oznacza to, że zmiany wprowadzone przez B są "scalone" w transakcję A.
  • Po B wykończenia, w każdym wyżej wymienionym przypadku A może zdecydować pogoda do kontynuowania i commit (który będzie prawdziwym zobowiązać się do DB, który obejmuje wszystkie zmiany, których autorem jest A i B [jeśli popełnione]) lub wycofania (czyli wolę przywrócić transakcję do stanu, w którym została utworzona, unieważniając wszystkie zmiany przez A + B).
+0

Propagacja.NESTED nie pomoże mi. Ponieważ jeśli B zostanie zakończone normalnie, a potem po ostatniej części A wyrzuci wyjątek, to również nie wycofa B, mimo że jest to moja intencja. – Spiderman

+0

@Spiderman: Nie, będzie. Zaktualizowałem swoją odpowiedź, podając dokładniejszy opis scenariusza. Spróbuj :) –

4

Podczas konfigurowania menedżera transakcji Wiosna, można ustawić właściwość o nazwie „globalRollbackOnParticipationFailure”. Jeśli zostanie ustawiona wartość false, wyjątek występujący w metodzie, która uczestniczy w istniejącej transakcji, nie oznaczy transakcji do wycofania. Transakcja jest zaznaczona tylko dla wycofania, jeśli wyjątek został usunięty z metody, która rozpoczęła transakcję.

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
    <property name="globalRollbackOnParticipationFailure" value="false" /> 
</bean> 

Aby uzyskać więcej informacji, patrz JavaDoc.

Powiązane problemy