Глава 33
Транзакции
Типичное enterprise приложение получает и хранит данные в одной или нескольких БД. Поскольку это информация критически важна для бизнес операций, она должна быть точной, достоверной и актуальной. Целосность данных может быть потеряна, если несколько приложений будут изменять данные одновременно. Целосность также будет нарушена, если данные останутся частично изменены ввиду какого-либо сбоя. Транзакции гарантируют целосность данных, предотвращая оба этих сценария. Транзакции контролируют совместный доступ к данным, а в случае сбоя гарантируют корректное восстановление данных.Что такое транзакция?
Для моделирования бизнес-транзакции программе может потребоваться выполнить несколько шагов, например
начало транзакции
проверка состояния счета
обновление состояния счета
запись информации в лог
коммит транзакции
Либо все шаги должны завершиться коректно, либо ни один из них. Иначе целосность данных нарушится. Транзакция может завершиться двумя путями: коммитом, либо откатом (rollback).
Управляемые контейнером транзакции (Container-Managed Transactions)
В enterprise bean с container-managed transaction demarcation границы транзакций выставляет EJB контейнер. Вы можете использовать container-managed transactions как с session так и с message-driven bean. В этом случае разработка упрощается, поскольку Вы не имеете дело с транзакциями явно.
Обычно контейнер начинает транзакцию сразу после начала метода и коммитит непосредственно перед выходом из метода. Каждый метод ассоциирован с одной транзакцией, встроенные или множественные транзакции внутри метода не доступны.
Бины, не должны использовать методы, которые пересекаются с определением границ транзакций, например методы commit, setAutoCommit, rollback класса java.sql.Connection или commit, rollback класса javax.jms.Session. Если это необходимо, то используйте application-managed transaction demarcation.
Также нельзя использовать интерфейс javax.transaction.UserTransaction.
Аттрибуты транзакции
Аттрибуты транзакции определяют охват транзакции. На рис. 33-1 ставится вопрос: необходимо ли открывать новую транзакцию? Ответ зависит от аттрибутов method-B()
Рис. 33-1
Аттрибуты могут принимать значения:
Required
RequiresNew
Mandatory
NotSupported
Supports
Never
Сводная таблица
Table 33-1 В таблице 33-1 показано поведение контейнера исходя в различных ситуациях при различных значениях аттрибутов.
Таблица 33-1.
Значение аттрибута | Клиентская транзакция | Транзакция метода |
---|---|---|
Required | None | T2 |
T1 | T1 | |
RequiresNew | None | T2 |
T1 | T2 | |
Mandatory | None | error |
T1 | T1 | |
NotSupported | None | None |
T1 | None | |
Supports | None | None |
T1 | T1 | |
Never | None | None |
T1 | Error |
Установка значения аттрибута
Аттрибуты определяюся с помощью анотации javax.ejb.TransactionAttribute, им присваивается одно из значений javax.ejb.TransactionAttributeType.
Можно аннотировать как отдельные методы, так и целые классы. Аннотация метода переопределяет аннотацию класса.
TransactionAttributeType содержит соответствующие значения:
Required: TransactionAttributeType.REQUIRED
RequiresNew: TransactionAttributeType.REQUIRES_NEW
Mandatory: TransactionAttributeType.MANDATORY
NotSupported: TransactionAttributeType.NOT_SUPPORTED
Supports: TransactionAttributeType.SUPPORTS
Never: TransactionAttributeType.NEVER
Ниже приведен пример использования аннотации
@TransactionAttribute(NOT_SUPPORTED)
@Stateful
public class TransactionBean implements Transaction {
...
@TransactionAttribute(REQUIRES_NEW)
public void firstMethod() {...}
@TransactionAttribute(REQUIRED)
public void secondMethod() {...}
public void thirdMethod() {...}
public void fourthMethod() {...}
}
Откат Container-Managed Transaction
Есть два способа откатить container-managed transaction. Первый: контейнер автоматически откатывает транзакцию, если брошен системный exception (в случае application exception откат не произойдет). Второй - можно вызвать метод EJBContext.setRollbackOnly.Synchronizing a Session Bean’s Instance Variables
Интерфейс SessionSynchronization позволяет stateful session бинам получать синхронизационные уведомлени. Контейнер будет вызывать соответствующие методы (afterBegin, beforeCompletion, and afterCompletion) в нужное время.
Недозволенные методы Container-Managed Transactions
Не следует пользоваться следующими методами:любыми методами javax.transaction.UserTransaction
Если они вам необходимы, пользуйтеся application-managed transactions.
Bean-Managed Transactions
При использовании bean-managed transaction demarcation, вы должны явно определять границы транзакции. Главное преимущество по сравнению с container-managed является возможность определять несколько транзакций в одном методе.
Ниже приведен псевдокод примера
begin transactionВо время кодирования application-managed transaction, необходимо решить что использовать: JDBC или JTA транзакции.
...
update table-a
...
if (condition-x)
commit transaction
else if (condition-y)
update table-b
commit transaction
else
rollback transaction
begin transaction
update table-c
commit transaction
JTA транзакции
JTA позволяет управлять транзакциями независимо от реализации. Сервер приложений реализует управление транзакциями с помощью Java Transaction Service (JTS).
Преимущество JTA в том, что можно охватывать несколько баз данных различных вендоров. Однако, Java EE transaction manager имеет ограничение: встроенные (nested) транзакции не поддерживаются. Другими словами, нельзя создать транзакцию для экземпляра, пока предыдущая не закончена.
Для определения границ транзакции вызываются методы begin, commit, and rollbac интерфейса javax.transaction.UserTransaction.
Возврат без коммита
В stateless session бинах с bean-managed transactions метод должен закоммитить или откатить транзакцию до возврата значения. Но stateful session bean не имеет такой обязанности.В stateful session bean ассоциация бина и транзакции сохраняется между вызовами.
Запрещенные методы в Bean-Managed Transactions
Не вызывайте методы getRollbackOnly and setRollbackOnly интерфейса EJBContext, вместо этого используйте getStatus и rollback интерфейса UserTransaction.Таймаут транзакции
Длч container-managed transactions можно использовать Admin Console для определения таймаута транзакций.
В Admin Console -> Configuration -> Transaction Service.
- На одной из закладок можно выставить значение таймаута (в секундах). Если транзакция не завершилась в течении этого времени - она будет откачена. Значение по умолчанию равно нулю, т.е. транзакции не имеют таймаута.
Для bean-managed используйте метод UserTransaction.setTransactionTimeout
Обновление нескольких баз данных
Бинам разрешается обновлять несколько баз данных в пределах одной транзакции. Ниже на рисунках показаны два возможных сценария.
На рис. 33-2 все обновления происходят в одной транзации.
Figure 33-2
Во втором случае (рис. 33-3), transaction managers Java EE сервера также гарантирует, что все обновления произойдут в пределах одной транзакции.
Figure 33-3
Комментариев нет:
Отправить комментарий