Transakcje ze Springiem i WZP

1. Przegląd

W tym samouczku omówimy właściwy sposób konfiguracji Spring Transactions , sposób korzystania z adnotacji @Transactional i typowe pułapki.

Aby uzyskać bardziej szczegółowe omówienie podstawowej konfiguracji trwałości, zapoznaj się z samouczkiem Spring with JPA.

Zasadniczo istnieją dwa różne sposoby konfigurowania transakcji - adnotacje i AOP - każdy z własnymi zaletami. Omówimy tutaj bardziej powszechną konfigurację adnotacji.

2. Skonfiguruj transakcje

Wiosna 3.1 wprowadza się @EnableTransactionManagement adnotacji , które możemy wykorzystać w @Configuration klasy i włączyć obsługę transakcyjną:

@Configuration @EnableTransactionManagement public class PersistenceJPAConfig{ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){ //... } @Bean public PlatformTransactionManager transactionManager(){ JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory( entityManagerFactoryBean().getObject() ); return transactionManager; } }

Jeśli jednak używamy projektu Spring Boot i mamy zależności spring-data- * lub spring-tx na ścieżce klasy, wówczas zarządzanie transakcjami zostanie domyślnie włączone .

3. Skonfiguruj transakcje za pomocą XML

Przed wersją 3.1 lub jeśli Java nie jest opcją, oto konfiguracja XML, przy użyciu adnotacji i obsługi przestrzeni nazw:

4. Adnotacja @Transactional

Po skonfigurowaniu transakcji możemy teraz dodać do beana adnotację @Transactional na poziomie klasy lub metody:

@Service @Transactional public class FooService { //... }

Adnotacja obsługuje również dalszą konfigurację :

  • Rozmnażanie Rodzaj transakcji
  • poziom izolacji transakcji
  • limitu czasu dla operacji owinięte transakcji
  • readOnly flag - podpowiedź dla dostawcy utrwalania, że transakcja powinna być tylko do odczytu
  • Wycofywanie zasady dotyczące transakcji

Zwróć uwagę, że - domyślnie wycofanie ma miejsce tylko w czasie wykonywania, z niezaznaczonymi wyjątkami. Zaznaczony wyjątek nie powoduje wycofania transakcji. Możemy oczywiście skonfigurować to zachowanie za pomocą parametrów adnotacji rollbackFor i noRollbackFor .

5. Potencjalne pułapki

5.1. Transakcje i pełnomocnictwa

Na wysokim poziomie Spring tworzy proxy dla wszystkich klas z adnotacją @Transactional - albo w klasie, albo w dowolnej z metod. Proxy umożliwia frameworkowi wstrzyknięcie logiki transakcyjnej przed i po uruchomionej metodzie - głównie w celu rozpoczęcia i zatwierdzenia transakcji.

Należy pamiętać, że jeśli transakcyjny komponent bean implementuje interfejs, domyślnie proxy będzie dynamicznym proxy Java. Oznacza to, że przechwytywane będą tylko wywołania metod zewnętrznych przychodzące przez serwer proxy. Żadne wywołanie samowywołania nie rozpocznie żadnej transakcji, nawet jeśli metoda ma adnotację @Transactional .

Innym zastrzeżeniem dotyczącym używania serwerów proxy jest to, że tylko metody publiczne powinny być opatrzone adnotacją @Transactional. Metody innych widoczności będą po prostu ignorować adnotacje po cichu, ponieważ nie są one zastępowane.

W tym artykule szczegółowo omówiono dalsze pułapki związane z serwerami proxy.

5.2. Zmiana poziomu izolacji

Możemy również zmienić poziom izolacji transakcji:

@Transactional(isolation = Isolation.SERIALIZABLE)

Zauważ, że zostało to faktycznie wprowadzone w Spring 4.1; jeśli uruchomimy powyższy przykład przed wiosną 4.1, to spowoduje:

org.springframework.transaction.InvalidIsolationLevelException : Standardowy JPA nie obsługuje niestandardowych poziomów izolacji - użyj specjalnego JpaDialect do implementacji JPA

5.3. Transakcje tylko do odczytu

ReadOnly flag zwykle generuje zamieszanie, zwłaszcza podczas pracy z WZP; z Javadoc:

Służy to tylko jako wskazówka dla rzeczywistego podsystemu transakcji; będzie to niekoniecznie spowodować niepowodzenie prób dostępu do zapisu. Menedżer transakcji, który nie może zinterpretować wskazówki tylko do odczytu, nie zgłosi wyjątku, gdy zostanie wyświetlony monit o transakcję tylko do odczytu.

Faktem jest, że nie możemy być pewni, że wstawianie lub aktualizacja nie nastąpi, gdy ustawiona jest flaga readOnly . To zachowanie jest zależne od dostawcy, podczas gdy JPA jest niezależny od dostawcy.

Ważne jest również, aby zrozumieć, że readOnly flaga ma znaczenie tylko wewnątrz transakcji. Jeśli operacja ma miejsce poza kontekstem transakcyjnym, flaga jest po prostu ignorowana. Prosty przykład wywołałby metodę z adnotacją:

@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )

z kontekstu nietransakcyjnego - transakcja nie zostanie utworzona, a flaga readOnly zostanie zignorowana.

5.4. Rejestrowanie transakcji

Pomocną metodą zrozumienia kwestii związanych z transakcjami jest dostrajanie logowania w pakietach transakcyjnych. Odpowiedni pakiet w Spring to „ org.springframework.transaction”, który powinien być skonfigurowany z poziomem logowania TRACE.

6. Wniosek

Omówiliśmy podstawową konfigurację semantyki transakcyjnej przy użyciu języka Java i XML, jak używać @Transactional oraz najlepszych praktyk strategii transakcyjnej.

Jak zawsze kod przedstawiony w tym artykule jest dostępny na Github.