Я читаю Управление транзакциями Java EE 7, и меня смущает концепция вложенной транзакции и функциональность EJBContext#setRollbackOnly()
.
Скажем, у меня есть два сеансовых компонента, Bean1Impl
и Bean2Impl
, и их подписи:
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class Bean1Impl implements Bean1 {
@Resource
private EJBContext context;
@TransactionAttribute(REQUIRED)
public void method1() {
try {
//some operations such as persist(), merge() or remove().
}catch(Throwable th){
context.setRollbackOnly();
}
}
}
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class Bean2Impl implements Bean2 {
@Resource
private EJBContext context;
@TransactionAttribute(REQUIRED)
public void method2() {
try {
//some operations such as persist(), merge() or remove().
//an exception has been thrown
}catch(Throwable th){
context.setRollbackOnly();
}
}
}
Как указано в учебнике по Java EE 7:
51.3.1.1 Обязательный атрибут
Если клиент выполняется внутри транзакции и вызывает метод корпоративного компонента, этот метод выполняется внутри транзакции клиента. Если клиент не связан с транзакцией, контейнер запускает новую транзакцию перед запуском метода.
Атрибут Required — это неявный атрибут транзакции для всех методов корпоративного компонента, работающих с разграничением транзакций, управляемых контейнером. Обычно вы не устанавливаете обязательный атрибут, если вам не нужно переопределить другой атрибут транзакции. Поскольку атрибуты транзакций являются декларативными, их можно легко изменить позже.
В этом случае мне не нужно указывать объявление аннотации @TransactionAttribute(REQUIRED)
в методах Bean1Impl#method1()
и Bean2Impl#method2()
. Я прав?
Таким образом, в приведенном выше коде транзакция Bean2Impl#method2()
будет выполняться внутри транзакции Bean1Impl#method1()
.
Могу ли я считать это вложенной транзакцией?
Если внутри метода Bean2Impl#method2()
было выброшено Exception
, что в конечном итоге привело бы к вызову метода EJBContext.setRollbackOnly()
из блока catch
и, как и ожидалось, он должен откатить операции, выполненные в блоке try
этого метода. Что в этом случае произойдет с транзакцией, а также с Bean1Impl#method1()
. Его тоже откатят? Я имею в виду:
Что произойдет, если будет звонок EJBContext.setRollbackOnly()
от Bean2Impl#method2()
и
Bean2Impl#method2()
вызывается из методаBean1Impl#method1()
перед любой операцией с базой данных, такой как сохранение, слияние или удаление.Bean2Impl#method2()
вызывается из методаBean1Impl#method1()
после любой операции с базой данных, такой как сохранение, слияние или удаление.
И, наконец, что произойдет, если метод Bean2Impl#method2()
будет выполнен успешно, но EJBContext.setRollbackOnly()
будет вызван из Bean1Impl#method1()
после успешного возврата Bean2Impl#method2()
?