Pytanie nie jest prywatne ani publiczne, pytanie brzmi: w jaki sposób jest wywoływane i jakiej implementacji AOP używasz!
Jeśli użyjesz (domyślnie) Spring AOP AOP, wszystkie funkcje AOP zapewniane przez Spring (jak @Transational
) zostaną wzięte pod uwagę tylko wtedy, gdy wywołanie przejdzie przez proxy. - Zwykle dzieje się tak, jeśli metoda z adnotacjami jest wywoływana z innej fasoli.
Ma to dwie konsekwencje:
- Ponieważ nie można wywoływać metod prywatnych z innej fasoli (wyjątkiem jest odbicie), ich
@Transactional
adnotacja nie jest brana pod uwagę.
- Jeśli metoda jest publiczna, ale jest wywoływana z tego samego komponentu bean, również nie zostanie wzięta pod uwagę (ta instrukcja jest poprawna tylko wtedy, gdy zostanie użyta (domyślnie) AOP Spring Proxy).
@ Patrz Spring Reference: Rozdział 9.6 9.6 Mechanizmy proxy
IMHO powinieneś użyć trybu aspektJ zamiast Spring Proxy, które pokonają problem. Aspekty transakcyjne AspectJ są wplecione nawet w metody prywatne (sprawdzone dla Spring 3.0).
Odpowiedź na twoje pytanie brzmi „nie” -
@Transactional
nie odniesie żadnego skutku, jeśli zostanie użyta do oznaczenia prywatnych metod. Generator proxy je zignoruje.Jest to udokumentowane w rozdziale 10.5.6 Podręcznika Spring :
źródło
Domyślnie ten
@Transactional
atrybut działa tylko podczas wywoływania metody z adnotacjami w odniesieniu do odwołania uzyskanego z applicationContext.Spowoduje to otwarcie transakcji:
To nie będzie:
Odniesienie wiosny: Korzystanie z @Transactional
źródło
Tak, można używać @Transactional na prywatnych metodach, ale jak wspomnieli inni, nie będzie to działać od razu po wyjęciu z pudełka. Musisz użyć AspectJ. Zajęło mi trochę czasu, aby dowiedzieć się, jak to działa. Podzielę się swoimi wynikami.
Wybrałem tkanie w czasie kompilacji zamiast tkania w czasie ładowania, ponieważ uważam, że jest to ogólnie lepsza opcja. Używam także Java 8, więc może być konieczne dostosowanie niektórych parametrów.
Najpierw dodaj zależność aspekjrt.
Następnie dodaj wtyczkę AspectJ, aby wykonać rzeczywiste tkanie kodu bajtowego w Maven (może to nie być minimalny przykład).
Na koniec dodaj to do swojej klasy config
Teraz powinieneś być w stanie używać @Transactional na prywatnych metodach.
Jedno zastrzeżenie do tego podejścia: Musisz skonfigurować IDE, aby mieć świadomość AspectJ, w przeciwnym razie, jeśli uruchomisz aplikację za pośrednictwem Eclipse, na przykład może nie działać. Upewnij się, że testujesz na bezpośredniej kompilacji Maven jako sprawdzian zdrowia.
źródło
Jeśli chcesz zawinąć prywatną metodę w transakcji i nie chcesz używać aspektuj, możesz użyć TransactionTemplate .
źródło
TransactionTemplate
użycie, ale proszę wywołać tę drugą metodę..RequiresTransaction
zamiast..InTransaction
. Zawsze wymieniaj rzeczy, które chcesz przeczytać rok później. Chciałbym również zastanowić się, czy naprawdę wymaga drugiej prywatnej metody: albo umieść jego treść bezpośrednio w anonimowejexecute
implementacji, albo jeśli stanie się to bałagan, może to wskazywać na podział implementacji na inną usługę, którą możesz następnie opatrzyć adnotacjami@Transactional
.Spring Docs to wyjaśniają
Innym sposobem jest użytkownik BeanSelfAware
źródło
BeanSelfAware
? Nie wygląda to na klasęOdpowiedź brzmi nie. Zobacz Spring Reference: Korzystanie z @Transactional :
źródło
W taki sam sposób, jak @loonis sugeruje użycie TransactionTemplate, można użyć tego komponentu pomocniczego (Kotlin):
Stosowanie:
Nie wiem, czy
TransactionTemplate
ponownie wykorzystasz istniejącą transakcję, czy nie, ale ten kod zdecydowanie.źródło