1. Введение
Spring обеспечивает поддержку как программных, так и декларативных транзакций.
1.1 Программные транзакции
При программных транзакциях код управления транзакциями должен быть написан в явном виде, чтобы зафиксировать, когда все успешно, и откатиться, если что-то пойдет не так. В этом случае код управления транзакциями тесно связан с бизнес-логикой.
1.2 Декларативные операции
Декларативные транзакции отделяют код управления транзакциями от бизнес-логики. Spring поддерживает декларативные транзакции, используя рекомендации по транзакциям (используя AOP) через конфигурацию XML в контексте Spring или с аннотацией @Transactional .
В этом уроке мы особенно будем интересоваться аннотацией @Transactional и тем, как она работает.
2. Реализация
Чтобы начать использовать аннотацию @Transactional в приложении на базе Spring, нам нужно сначала включить аннотации в нашем приложении Spring, добавив необходимую конфигурацию в контекстный файл Spring —
1
|
<tx:annotation-driven transaction-manager= "txManager" /> |
Далее следует определить компонент управления транзакциями с тем же именем, которое указано в приведенном выше значении атрибута менеджера транзакций .
Менеджеры транзакций могут быть:
2.1 Менеджер транзакций источника данных
1
2
3
4
|
< bean id = "txManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > < property name = "dataSource" ref = "datasource" /> </ bean > |
2.2 Диспетчер транзакций Hibernate
1
2
3
4
|
< bean id = "txManager" class = "org.springframework.orm.hibernate3.HibernateTransactionManager" > < property name = "sessionFactory" ref = "sessionFactory" /> </ bean > |
2.3 JPA Менеджер транзакций
1
2
3
4
|
< bean id = "txManager" class = "org.springframework.orm.jpa.JpaTransactionManager" > < property name = "entityManagerFactory" ref = "entityManagerFactory" /> </ bean > |
Теперь мы готовы использовать аннотацию @Transactional на уровне класса или метода.
1
2
3
4
|
@Transactional (value = "myTransactionManager" , propagation = Propagation.REQUIRED, readOnly = true ) public void myMethod() { ... } |
3. Ссылки по теме
4. Понимание аннотации @Transactional
На высоком уровне, когда класс объявляет @Transactional для себя или своих членов, Spring создает прокси, который реализует тот же интерфейс (ы), что и класс, который вы аннотируете. Другими словами, Spring оборачивает бин в прокси, и сам бин об этом не знает. Прокси-сервер предоставляет Spring способ внедрить поведение до, после или вокруг вызовов методов в объект, который проксируется.
Внутренне, это то же самое, что использовать совет по транзакциям (используя AOP), когда прокси создается первым и вызывается до / после метода целевого компонента.
Сгенерированный прокси-объект поставляется с TransactionInterceptor , который создается Spring. Поэтому, когда метод @Transactional вызывается из клиентского кода, TransactionInterceptor сначала вызывается из прокси-объекта, который начинает транзакцию и в конечном итоге вызывает метод для целевого компонента. Когда вызов завершается, TransactionInterceptor фиксирует / откатывает транзакцию соответственно.
Обратите внимание, что через прокси проходят только вызовы «извне» целевого компонента.
5. Понимание атрибутов распространения и чтения только для комментариев
5.1 Транзакция только для чтения
Если вы явно не установите атрибут readOnly в true , у вас будут транзакции чтения / записи.
Всегда лучше явно указывать атрибут readOnly , поскольку из-за этого мы заметили значительные улучшения производительности в Hibernate.
5.2 Распространение транзакции
По умолчанию ТРЕБУЕТСЯ распространение транзакции, что означает, что одна и та же транзакция будет распространяться от транзакционного вызывающего абонента до транзакционного вызываемого. Это создаст новую транзакцию или повторно использует ту, которая доступна. Например, если транзакция только для чтения вызывает метод транзакции чтения-записи, вся транзакция будет доступна только для чтения.
В зависимости от атрибута распространения транзакции (например, для REQUIRES_NEW ), иногда существующая транзакция в какой-то момент приостанавливается / приостанавливается, новая всегда запускается и в конечном итоге фиксируется, и после этого первая транзакция возобновляется.
5.3 Уровень изоляции
Уровень изоляции определяет договор между транзакциями.
- Read Uncommitted — разрешает грязное чтение, когда транзакция еще не зафиксирована потоком, а другой поток читает грязные данные.
- Read Committed — не допускает грязного чтения. Позволяет только потоку читать значения, которые уже были зафиксированы другими запущенными транзакциями в других потоках.
- Повторяемое чтение — если одни и те же данные читаются дважды в одной и той же транзакции, они всегда будут одинаковыми. Этот уровень гарантирует, что любые прочитанные данные не могут измениться.
- Сериализуемый — Транзакции происходят с блокировкой на всех уровнях (чтение, диапазон и блокировка записи), из-за чего они выполняются в фиксированной последовательности. Он не допускает одновременных транзакций и приводит к снижению производительности.
С уровнем изоляции Repeatable Read состояние базы данных поддерживается с начала транзакции. Если вы извлекаете значение в сеансе 1 , то обновляете это значение в сеансе 2 , и его повторное получение в сеансе 1 возвращает те же результаты.
6. Исходный код скачать
Ссылка: | Понимание аннотации транзакций весной от нашего партнера JCG Абхиманью Прасада в блоге jCombat . |