В Enterprise-бине с управляемыми контейнером транзакциями границы транзакций устанавливаются контейнером EJB. Управляемые контейнером транзакции можно использовать с любым типом Enterprise-бина: сессионным или управляемым сообщениями. Управляемые контейнером транзакции упрощают разработку, поскольку код Enterprise-бина явно не отмечает границы транзакции. В коде отсутствуют операторы, которые начинают и заканчивают транзакцию. По умолчанию, если разграничение транзакции не указано, Enterprise-бины используют транзакцию, управляемую контейнером.
Как правило, контейнер начинает транзакцию непосредственно перед запуском метода Enterprise-бина и фиксирует транзакцию непосредственно перед завершением метода. Каждый метод может быть связан с одной транзакцией. Вложенные или множественные транзакции в методе не разрешены.
Управляемые контейнером транзакции не требуют, чтобы все методы были связаны с транзакциями. При разработке бина вы можете установить атрибуты транзакции, чтобы указать, какие методы бина связаны с транзакциями.
Enterprise-бины, использующие разграничение транзакций, управляемое контейнером, не должны использовать методы управления транзакциями, которые мешают разграничению транзакций контейнером. Примерами таких методов являются методы commit
, setAutoCommit
и rollback
для java.sql.Connection
или методы commit
и rollback
для javax.jms.Session
. Если вам требуется контроль над разграничением транзакций, вы должны использовать разграничение транзакций, управляемое приложением.
Enterprise-бины, использующие разграничение управляемых контейнером транзакций, также не должны использовать интерфейс javax.transaction.UserTransaction
.
Атрибуты транзакции
Атрибут транзакции контролирует область действия транзакции. На рисунке 54-1 показано, почему ею важно управлять. На диаграмме method-A
начинает транзакцию, а затем вызывает method-B
у Bean-2
. Когда method-B
выполняется, он запускается в рамках транзакции, запущенной method-A
, или выполняется в новой транзакции? Ответ зависит от атрибута транзакции method-B
.
Рисунок 54-1 Область действия транзакции

Атрибут транзакции может иметь одно из следующих значений:
-
Required
-
RequiresNew
-
Mandatory
-
NotSupported
-
Supports
-
Never
Атрибут Required
Если клиент работает в транзакции и вызывает метод Enterprise-бина, метод выполняется в транзакции клиента. Если клиент не связан с транзакцией, контейнер запускает новую транзакцию перед запуском метода.
Атрибут Required
является неявным атрибутом транзакции для всех методов Enterprise-бина, работающих с разграничением транзакций, управляемым контейнером. Обычно атрибут Required
не устанавливается, если не нужно переопределять другой атрибут транзакции. Поскольку атрибуты транзакции являются декларативными, их легко можно изменить позже.
Атрибут RequiresNew
Если клиент работает в транзакции и вызывает метод Enterprise-бина, контейнер выполняет следующие шаги:
-
Приостанавливает транзакцию клиента
-
Запускает новую транзакцию
-
Делегирует вызов метода
-
Возобновляет транзакцию клиента после завершения метода
Если клиент не связан с транзакцией, контейнер запускает новую транзакцию перед запуском метода.
Атрибут requireNew
используется, если нужна уверенность, что метод всегда выполняется в новой транзакции.
Атрибут Mandatory
Если клиент работает в транзакции и вызывает метод Enterprise-бина, метод выполняется в транзакции клиента. Если клиент не связан с транзакцией, контейнер выбрасывает исключение TransactionRequiredException
.
Атрибут Mandatory
используется, если метод Enterprise-бина должен использовать транзакцию клиента.
Атрибут NotSupported
Если клиент работает в транзакции и вызывает метод Enterprise-бина, контейнер приостанавливает транзакцию клиента перед вызовом метода. После завершения метода контейнер возобновляет транзакцию клиента.
Если клиент не связан с транзакцией, контейнер не запускает новую транзакцию перед запуском метода.
Атрибут NotSupported
используется для методов, которые не требуют транзакций. Поскольку с транзакциями связаны накладные расходы, этот атрибут может повысить производительность.
Атрибут Supports
Если клиент работает в транзакции и вызывает метод Enterprise-бина, метод выполняется в транзакции клиента. Если клиент не связан с транзакцией, контейнер не запускает новую транзакцию перед запуском метода.
Поскольку транзакционное поведение метода может отличаться, следует использовать атрибут Supports
с осторожностью.
Атрибут Never
Если клиент работает в транзакции и вызывает метод Enterprise-бина, контейнер генерирует RemoteException
. Если клиент не связан с транзакцией, контейнер не запускает новую транзакцию перед запуском метода.
Обзор атрибутов транзакции
Таблица 54-1 суммирует влияние атрибутов транзакции. Обе транзакции T1
и T2
управляются контейнером. Транзакция T1
связана с клиентом, который вызывает метод в Enterprise-бине. В большинстве случаев клиент — это другой Enterprise-бин. Транзакция T2
запускается контейнером непосредственно перед выполнением метода.
В последнем столбце таблицы 54-1 слово «None» означает, что бизнес-метод не выполняется в транзакции, управляемой контейнером. Однако вызовы базы данных в таком бизнес-методе могут управляться менеджером транзакций системы управления базами данных.
Таблица 54-1 Атрибуты транзакции и область действия
Атрибут транзакции |
Транзакция клиента |
Транзакция бизнес-метода |
Required
|
None |
T2 |
Required
|
T1 |
T1 |
RequiresNew
|
None |
T2 |
RequiresNew
|
T1 |
T2 |
Mandatory
|
None |
Error |
Mandatory
|
T1 |
T1 |
NotSupported
|
None |
None |
NotSupported
|
T1 |
None |
Supports
|
None |
None |
Supports
|
T1 |
T1 |
Never
|
None |
None |
Never
|
T1 |
Error |
Установка атрибутов транзакции
Атрибуты транзакции задаются путём аннотирования класса или метода Enterprise-бина аннотацией javax.ejb.TransactionAttribute
и установки для неё одной из констант javax.ejb.TransactionAttributeType
.
Если аннотировать класс Enterprise-бина с помощью @TransactionAttribute
, указанный TransactionAttributeType
будет применён ко всем бизнес-методам в классе. При аннотирования бизнес-метода с помощью @TransactionAttribute
TransactionAttributeType
применяется только к этому методу. Если аннотацией @TransactionAttribute
аннотированы и класс, и метод, атрибут TransactionAttributeType
метода переопределяет атрибут TransactionAttributeType
класса.
Константы TransactionAttributeType
, перечисленные в таблице 54-2, инкапсулируют атрибуты транзакции, описанные ранее в этом разделе.
Таблица 54-2 Константы TransactionAttributeType
Атрибут транзакции |
Константа TransactionAttributeType |
Required
|
TransactionAttributeType.REQUIRED
|
RequiresNew
|
TransactionAttributeType.REQUIRES_NEW
|
Mandatory
|
TransactionAttributeType.MANDATORY
|
NotSupported
|
TransactionAttributeType.NOT_SUPPORTED
|
Supports
|
TransactionAttributeType.SUPPORTS
|
Never
|
TransactionAttributeType.NEVER
|
В следующем фрагменте кода показано, как использовать аннотацию @TransactionAttribute
:
@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() {...}
}
В этом примере атрибут транзакции класса TransactionBean
был установлен в NotSupported
, firstMethod
был установлен в requireNew
, и secondMethod
был установлен в Required
. Поскольку @TransactionAttribute
для метода переопределяет @TransactionAttribute
для класса, вызовы firstMethod
создадут новую транзакцию и вызов secondMethod
будет либо запущен в текущей транзакции, либо начнёт новую транзакцию. Вызовы thirdMethod
и fourthMethod
происходят не в транзакции.
Откат транзакции, управляемой контейнером
Существует два способа откатить транзакцию, управляемую контейнером. Во-первых, если выдаётся системное исключение, контейнер автоматически откатит транзакцию. Во-вторых, вызывая метод setRollbackOnly
интерфейса EJBContext
, метод бина сигнализирует контейнеру откатить транзакцию. Если бин генерирует исключение приложения, откат не выполняется автоматическим, но может быть инициирован вызовом setRollbackOnly
.
Синхронизация переменных объекта сессионного бина
Необязательный интерфейс SessionSynchronization
позволяет объектам сессионного компонента с сохранением состояния получать уведомления о синхронизации транзакций. Например, вы можете синхронизировать переменные объекта Enterprise-бина с соответствующими значениями в базе данных. Контейнер вызывает методы SessionSynchronization
(afterBegin
, beforeCompletion
и afterCompletion
) на каждом из основных этапов транзакции.
Метод afterBegin
информирует объект о начале новой транзакции. Контейнер вызывает afterBegin
непосредственно перед вызовом бизнес-метода.
Контейнер вызывает метод beforeCompletion
после завершения бизнес-метода, но непосредственно перед фиксацией транзакции. Метод beforeCompletion
является последней возможностью для сессионного компонента откатить транзакцию (путём вызова setRollbackOnly
).
Метод afterCompletion
указывает, что транзакция завершена. Этот метод имеет единственный параметр boolean
, значение которого равно true
, если транзакция была зафиксирована, и false
, если был выполнен откат.
Методы, не разрешённые в транзакциях, управляемых контейнером
Недопустимо вызывать какой-либо метод, который может помешать разграничению транзакции, установленному контейнером. Следующие методы запрещены:
-
Методы commit
, setAutoCommit
и rollback
для java.sql.Connection
-
Метод getUserTransaction
для javax.ejb.EJBContext
-
Любой метод javax.transaction.UserTransaction
Однако допускается использовать эти методы для установки границ в управляемых приложением транзакциях.