Jestem nowy w Spring Transaction. Coś, co wydało mi się naprawdę dziwne, prawdopodobnie dobrze to zrozumiałem.
Chciałem mieć transakcję na poziomie metody i mam metodę wywołującą w tej samej klasie i wygląda na to, że nie podoba mi się to, musi być wywoływana z oddzielnej klasy. Nie rozumiem, jak to możliwe.
Jeśli ktoś ma pomysł, jak rozwiązać ten problem, byłbym bardzo wdzięczny. Chciałbym użyć tej samej klasy do wywołania metody transakcyjnej z adnotacjami.
Oto kod:
public class UserService {
@Transactional
public boolean addUser(String userName, String password) {
try {
// call DAO layer and adds to database.
} catch (Throwable e) {
TransactionAspectSupport.currentTransactionStatus()
.setRollbackOnly();
}
}
public boolean addUsers(List<User> users) {
for (User user : users) {
addUser(user.getUserName, user.getPassword);
}
}
}
java
spring
aspectj
spring-aop
Mikrofon
źródło
źródło
TransactionTemplate
podejście: stackoverflow.com/a/52989925/355438Odpowiedzi:
Jest to ograniczenie Spring AOP (dynamiczne obiekty i cglib ).
Jeśli skonfigurujesz Springa, aby używał AspectJ do obsługi transakcji, twój kod będzie działał.
Prostą i prawdopodobnie najlepszą alternatywą jest refaktoryzacja kodu. Na przykład jedna klasa obsługująca użytkowników i jedna przetwarzająca każdego użytkownika. Wtedy domyślna obsługa transakcji za pomocą Spring AOP będzie działać.
Wskazówki dotyczące konfiguracji obsługi transakcji z AspectJ
Aby umożliwić Springowi używanie AspectJ do transakcji, musisz ustawić tryb na AspectJ:
Jeśli używasz Springa ze starszą wersją niż 3.0, musisz również dodać to do swojej konfiguracji Springa:
źródło
Problem polega na tym, że serwery proxy AOP Springa nie rozszerzają się, ale raczej opakowują instancję usługi w celu przechwytywania połączeń. W efekcie każde wywołanie „this” z Twojej instancji usługi jest bezpośrednio wywoływane w tej instancji i nie może być przechwycone przez opakowujący serwer proxy (proxy nie wie nawet o takim wywołaniu). Wspomniano już o jednym rozwiązaniu. Innym fajnym rozwiązaniem byłoby po prostu wstrzyknięcie przez Spring instancji usługi do samej usługi i wywołanie metody na wstrzykniętej instancji, która będzie serwerem proxy obsługującym transakcje. Ale pamiętaj, że może to mieć również złe skutki uboczne, jeśli Twój komponent bean nie jest singletonem:
źródło
UserService
ma zasięg pojedynczy? A jeśli to ten sam obiekt?Dzięki Spring 4 możliwe jest Self autowired
źródło
Zaczynając od Java 8 istnieje inna możliwość, którą wolę z powodów podanych poniżej:
Takie podejście ma następujące zalety:
1) Może być stosowany do metod prywatnych . Nie musisz więc przerywać hermetyzacji, upubliczniając metodę, aby spełnić ograniczenia Spring.
2) Ta sama metoda może być wywołana w ramach różnych propagacji transakcji i od wywołującego zależy wybór odpowiedniej. Porównaj te 2 linie:
3) Jest wyraźny, a przez to bardziej czytelny.
źródło
TransactionHandler
jako podklasę, a podklasaTransactionHandler
wywoła te dwie metody w superklasie, czy nadal będę w stanie uzyskać korzyści@Transactional
zgodnie z zamierzeniami?Oto moje rozwiązanie do samodzielnego wywoływania :
źródło
Możesz automatycznie przypisać BeanFactory w tej samej klasie i wykonać
getBean(YourClazz.class)
Automatycznie przekaże twoją klasę i weźmie pod uwagę twoją @Transactional lub inną adnotację aop.
źródło
Problem jest związany z klasami obciążenia sprężyn i proxy. To nie zadziała, dopóki nie napiszesz swojej wewnętrznej metody / transakcji w innej klasie lub nie przejdziesz do innej klasy, a następnie ponownie przejdziesz do swojej klasy i nie napiszesz wewnętrznej metody zagnieżdżonej transkacji.
Podsumowując, wiosenne proxy nie pozwalają na scenariusze, z którymi się mierzysz. musisz napisać drugą metodę transakcji w innej klasie
źródło
Oto, co robię dla małych projektów z tylko marginalnym wykorzystaniem wywołań metod w tej samej klasie. Zdecydowanie zaleca się, aby dokumentacja w kodzie była dziwna dla współpracowników. Ale działa z singletonami , jest łatwy do przetestowania, prosty, szybki do osiągnięcia i oszczędza mi pełnego oprzyrządowania AspectJ. Jednak w przypadku bardziej intensywnego użytkowania radziłbym rozwiązanie AspectJ, jak opisano w odpowiedzi Espens.
źródło