1. Общ преглед
Този урок ще обсъди правилния начин за конфигуриране на пролетните транзакции , как да използвате анотацията @Transactional и често срещани клопки.
За по-задълбочена дискусия относно основната конфигурация за постоянство, вижте урока Spring with JPA.
По принцип има два различни начина за конфигуриране на транзакции - анотации и AOP - всеки със своите предимства. Тук ще обсъдим по-често срещаните конфигурации за пояснения.
2. Конфигуриране на транзакции
Пролет 3.1 въвежда на @EnableTransactionManagement анотация , които можем да използваме в @Configuration клас и дава възможност за сделка подкрепа:
@Configuration @EnableTransactionManagement public class PersistenceJPAConfig{ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){ //... } @Bean public PlatformTransactionManager transactionManager(){ JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory( entityManagerFactoryBean().getObject() ); return transactionManager; } }
Ако обаче използваме проект Spring Boot и имаме зависимости spring-data- * или spring-tx от пътя на класа, тогава управлението на транзакциите ще бъде активирано по подразбиране .
3. Конфигурирайте транзакции с XML
Преди 3.1 или ако Java не е опция, ето XML конфигурацията, използваща управлявана от анотация и поддръжка на пространство от имена:
4. @Transactional Annotation
С конфигурирани транзакции вече можем да анотираме боб с @Transactional на ниво клас или метод:
@Service @Transactional public class FooService { //... }
Анотацията поддържа и по-нататъшна конфигурация :
- типа на разпространение на транзакцията
- на ниво на изолация на сделката
- а Timeout за операцията обвит от сделката
- а само за четене флаг - намек за доставчика на постоянство, че сделката трябва да се чете само
- на намаление на цените правила за сделката
Имайте предвид, че - по подразбиране връщането се случва само по време на изпълнение, непроверени изключения. Провереното изключение не задейства връщане на транзакцията. Можем, разбира се, да конфигурираме това поведение с параметрите за анотация на rollbackFor и noRollbackFor .
5. Потенциални клопки
5.1. Транзакции и пълномощници
На високо ниво Spring създава прокси за всички класове, анотирани с @Transactional - или за класа, или за някой от методите. Проксито позволява на рамката да инжектира транзакционна логика преди и след текущия метод - главно за стартиране и фиксиране на транзакцията.
Това, което е важно да имате предвид, е, че ако транзакционният компонент изпълнява интерфейс, по подразбиране проксито ще бъде Java Dynamic Proxy. Това означава, че ще бъдат прихванати само извиквания на външни методи, които влизат през проксито. Всички извиквания за самоизвикване няма да стартират транзакции, дори ако методът има анотацията @Transactional .
Друга забележка при използването на прокси е, че само публични методи трябва да бъдат анотирани с @Transactional. Методите за всяка друга видимост просто игнорират анотацията безшумно, тъй като те не са прокси.
Тази статия разглежда тук подробно допълнителни подводни камъни.
5.2. Промяна на нивото на изолация
Също така можем да променим нивото на изолиране на транзакциите:
@Transactional(isolation = Isolation.SERIALIZABLE)
Имайте предвид, че това всъщност е въведено през пролет 4.1; ако стартираме горния пример преди Spring 4.1, това ще доведе до:
org.springframework.transaction.InvalidIsolationLevelException : Стандартният JPA не поддържа персонализирани нива на изолация - използвайте специален JpaDialect за вашата JPA реализация
5.3. Транзакции само за четене
В ReadOnly знаме обикновено генерира объркване, особено когато се работи с СПА; от Javadoc:
Това просто служи като намек за действителната подсистема на транзакциите; не е задължително да доведе до неуспех на опитите за достъп до запис. Мениджър на транзакции, който не може да интерпретира подсказката само за четене, няма да създаде изключение, когато бъде поискан транзакция само за четене.
Факт е, че не можем да сме сигурни, че вмъкване или актуализация няма да се случи, когато е зададен флагът readOnly . Това поведение зависи от доставчика, докато JPA е агностично от доставчика.
Също така е важно да се разбере, че флагът readOnly е уместен само в рамките на транзакция. Ако дадена операция се случи извън контекста на транзакцията, флагът просто се игнорира. Един прост пример за това би извикал метод, коментиран с:
@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )
от нетранзакционен контекст - транзакцията няма да бъде създадена и флагът readOnly ще бъде игнориран.
5.4. Регистрация на транзакции
Полезен метод за разбиране на свързаните с транзакциите проблеми е фината настройка на регистрирането в транзакционните пакети. Съответният пакет през пролетта е „ org.springframework.transaction“, който трябва да бъде конфигуриран с ниво на регистриране на TRACE.
6. Заключение
Ние разгледахме основната конфигурация на транзакционната семантика, използвайки Java и XML, как да използваме @Transactional и най-добрите практики на транзакционна стратегия.
Както винаги, кодът, представен в тази статия, е достъпен в Github.