2011-11-09 12 views
7

Mam klasę @Service, która ma metodę @Transactional, która wywołuje inną metodę @Transactional na tej samej klasie. Testowałem zachowanie wycofywania i stwierdziłem, że nie działa poprawnie. Kod wygląda mniej więcej tak:Metoda zagnieżdżonych @Transactional i wycofanie

@Service 
public class DefaulService implements ervice 
{ 
    @Transactional 
    public void methodOne() 
    { 
     methodTwo(); 

      //question edited 
      //this seems to be the problem 
      this.serviceDAO.executeUpdateOperation(); 

     //test rollback 
     throw new RuntimeException(); 
    } 

    @Transactional 
    public void methodTwo() 
    { 
     //DAO stuff 
    } 
} 

Po uruchomieniu methodOne sprawdzić bazę danych, a zmiany są tam, choć dziennik pokazuje „JDBCTransaction - wycofywania”.

Jeśli wywołasz metodę methodTwo osobno i dodasz wyjątek na końcu, zmiany zostaną wycofane poprawnie.

Czy istnieje sposób, aby methodOne poprawnie wycofać zmiany, które wystąpiły podczas zagnieżdżonego @ Transakcji? Miałem wrażenie, że domyślna propagacja REQUIRED doprowadziłaby do tego, ale wydaje się, że nie działa. Dzięki

UPDATE

Ok, właśnie zauważyłem coś innego. Tuż przed wyrzuceniem wyjątku wywołuję dao usługi i wykonuję ręczną aktualizację przez "executeUpdate". Jeśli skomentuję ten wiersz, zagnieżdżone wycofanie działa. Wygląda więc na to, że problem polega na wywołaniu DAO i uruchomieniu zapytania executeUpdate. Ale czy nie powinno to również przebiegać w ramach bieżącej transakcji?

+0

Czy zdajesz sobie sprawę, że wywołując 'methodTwo()' z 'methodOne()' '@ Transactional' adnotacja nad poprzednim jest ignorowana? Zobacz mój [artykuł] (http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html) w celu uzyskania dalszych szczegółów. Jednak to nie powoduje problemów, ale warto je poznać. –

+0

Tak, ale ponieważ metoda MethodTwo może być wywoływana niezależnie, w takich przypadkach potrzebuje własnej adnotacji. W tej chwili jestem zaskoczony, dlaczego metoda executeUpdate powoduje zatwierdzenie transakcji, chociaż być może jest to zachowanie domyślne. – JayPea

+1

czym jest propagacja transakcji z serviceDao? Czy to TY przypadkiem REQUIRES_NEW? – Hendrik

Odpowiedz

1

Zdecydowanie uzyskujesz instancję "ervice" z fabryki fasoli, gdy nazywasz metody, prawda? Fabryka fasoli musi ustawić proxy, które implementuje logikę transakcyjną wokół każdego wywołania metody. Miałem wrażenie, że działa to tylko wtedy, gdy "osoby postronne" wywołują metody za pośrednictwem serwera proxy i niekoniecznie działają, gdy jedna metoda wywołuje inną, ponieważ ta metoda jest bezpośrednim wywołaniem wewnątrz obiektu implementacji i nie przechodzi przez proxy AOP.

+0

To zależy od tego, jakiego rodzaju podejścia AOP używasz. Sprawdź [link] (http://nurkiewicz.blogspot.com/2011/10/spring-pitfalls-proxying.html) autorstwa Tomasza Nurkiewicza. Również to nie może wyjaśnić zachowania, które opisuje JayPea. –