Transakcja pozwala na łatwe zaaplikowanie zmian w wielokrokowej logice w jednym momencie. Zapewnia, że wszystkie zmiany zostaną zaaplikowane albo żadne.
Modyfikując dane w wielu krokach może coś pójść nie tak. Jeśli te kroki są objęte transakcją, wszystkie zmiany zostaną cofnięte.
Relacyjne bazy danych są transakcyjne. Wspierają takie operacje.
Proces po stronie bazy danych:
- Rozpoczęcie transakcji. Alokacja odpowiednich zasobów.
- Modyfikacja danych (wykonywanie operacji INSERT, UPDATE, DELETE na różnych tabelach). Jest to robione w ramach osobnej sesji. Lokalne zmiany nie są widoczne w innych sesjach.
- Zakończenie transakcji:
Zatwierdzenie (commit) – wszystkie zmiany są zapisywane. Inne sesje będą widziały zmiany. Zostają zwolnione zasoby.
Wycofanie zmian (rollback) – lokalne zmiany zostają wycofane. Zostają zwolnione zasoby.
@Transactional w Spring
W Spring dostępny jest mechanizm wspierający obsługę transakcji za pomocą adnotacji @Transactional.
Jak działa ta adnotacja?
1. Włącza obsługę transakcji.
2. Dostarcza API dla frameworka ORM. To ORM odpowiada za wymianę danych z bazą danych. Spring nie wysyła żadnych zapytań do bazy danych.
3. Dodaje logikę, która jest wywoływana przed i po metodzie:
- rozpoczyna transakcję lub używa wcześniej rozpoczętej transakcji przed wejściem do metody.
- umożliwia dwukierunkową integracje Springa z ORM. Przekazuje połączenie do bazy danych do ORM. Informuje ORM o zakończeniu transakcji.
- uruchamia mechanizmy monitorujące wykonywanie operacji.
- zatwierdza lub wycofuje zmiany na bazie danych po wyjściu z metody.
Zmiany są wycofywane, jeśli zostanie wyrzucony jakiś wyjątek. Domyślnie checked exception nie powodują wycofania zmian. Musimy dodać wtedy odpowiednią konfigurację.
Jak to działa?
Kiedy dana metoda jest oznaczona adnotacją, Spring przechwytuje wywołanie i na naszą metodę nakłada proxy (w zależności od ustawień). Proxy uruchamia interceptor, który zarządza transakcją.
Aby adnotacja zadziałała trzeba spełnić warunki:
- metoda musi być publiczna,
- klasa, w której znajduje się metoda musi być beanem springowym,
- metoda musi być wywoływana przez inny bean springowy.
Typy propagacji transakcji
Typy te określają w jaki sposób mają zachowywać się transakcje. Mamy metodę oznaczoną @Transactional i wewnątrz jej jest kolejna metoda oznaczona adnotacją @Transactional.
Typ określa np. czy zostanie wykorzystana już istniejąca transakcja, czy zostanie utworzona kolejna odrębna transakcja.
Typ REQUIRED
Jest to domyślny typ. Dlatego nie podajemy żadnego argumentu w adnotacji @Transactional.
Przy wejściu do metody oznaczonej @Transactional Spring sprawdzi czy istnieje transakcja rozpoczęta wyżej.
Jeśli tak to logika zostanie zaaplikowana do istniejącej transakcji.
Jeśli nie to utworzy nową transakcję.
Typ SUPPORTS
Przy wejściu do metody sprawdzi czy istnieje transakcja rozpoczęta wyżej.
Jeśli tak to istniejąca transakcja zostanie użyta.
Jeśli nie to kod zostanie wykonany bez żadnej transakcji.
Typ MANDATORY
Przy wejściu do metody sprawdzi czy istnieje transakcja rozpoczęta wyżej.
Jeśli tak to istniejąca transakcja zostanie użyta.
Jeśli nie to zostanie wyrzucony wyjątek.
Typ REQUIRES_NEW
Przy wejściu do metody sprawdzi czy istnieje transakcja rozpoczęta wyżej.
Jeśli tak to zostanie wstrzymana i stworzona nowa.
Jeśli nie to zostanie stworzona nowa.
Po zakończeniu tej transakcji zewnętrzna transakcja dalej zoobowiązuje. W przypadku wyrzucenia wyjątku w zewnętrznej transakcji, to co zostało wykonane w wewnętrznej transakcji nie zostanie wycofane.
Typ NOT_SUPPORTED
Przy wejściu do metody sprawdzi czy istnieje transakcja rozpoczęta wyżej.
Jeśli tak to zostanie wstrzymana i metoda zostanie wykonana bez transakcji.
Jeśli nie to metoda zostanie wykonana bez transakcji.
Typ NEVER
Metoda jest wykonywana bez transakcji. Jeśli transakcja wcześniej istniała wyrzucany jest wyjątek.
Typ NESTED
Działa tylko dla połączeń JDBC. Nie działa dla Hibernate. Przy wejściu do metody sprawdzi czy istnieje transakcja rozpoczęta wyżej.
Jeśli tak to oznacza to miejsce jako savepoint. Jednak jeśli zostanie wyrzucony wyjątek w tej metodzie to wszystko zostanie wycofane tylko do tego miejsca.
Jeśli nie to transakcja zachowuje się normalnie.
Tutaj możesz sięgnąć po więcej: Jak działa adnotacja @Transactional w Springu
Jeśli natomiast chcesz dowiedzieć się więcej o Springu to zapraszam tutaj: Spring Security – jak skutecznie zabezpieczać aplikacje i Spring Webflux i programowanie reaktywne
