EJB-транзакции в локальных методах-вызовах
В следующей настройке работает ли метод B в (новой) транзакции?
EJB, имеющий два метода, метод A и метод B
public class MyEJB implements SessionBean
public void methodA() {
doImportantStuff();
methodB();
doMoreImportantStuff();
}
public void methodB() {
doDatabaseThing();
}
}
EJB управляется контейнером с помощью метода B в require_new транзакции и метода A в требуемой транзакции. Таким образом:
<container-transaction id="MethodTransaction_1178709616940">
<method id="MethodElement_1178709616955">
<ejb-name>MyName</ejb-name>
<method-name>*</method-name>
<trans-attribute>Required</trans-attribute>
</method>
<method id="MethodElement_1178709616971">
<ejb-name>MyName</ejb-name>
<method-name>methodB</method-name>
</method>
<trans-attribute>RequiresNew</trans-attribute>
</container-transaction>
Теперь позвольте другому методу вызова EJB с вызовом метода EJB.
methodA теперь выполняется в транзакции. Будет ли последующий вызов методаB из метода A выполняться в той же транзакции или выполняется в новой транзакции?
(ум, это фактический код здесь. Нет явного ejb-вызова метода B)
Ответы
Ответ 1
Ваш вызов methodB()
является обычным вызовом метода, не перехваченным контейнером EJB; во время выполнения контейнер EJB будет вводить proxy, а не экземпляр вашего класса, это то, как он перехватывает вызовы и настраивает перед вызовом вашего метода. Если вы используете this
, вы вызываете метод напрямую, а не через прокси. Следовательно, оба метода будут использовать одну и ту же транзакцию, независимо от того, что определено в ejb-jar.xml для вызовов через интерфейсы EJB.
Ответ 2
добавить SessionContext и запросить его для своего прокси-сервера:
@Stateless
public class UserFacade implements UserFacadeLocal {
@Resource
private SessionContext context;
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
private void create(User user) {
System.out.println("Users Count: "+count()); //invocation#1
System.out.println("Users Count Through Context: "+context.getBusinessObject(UserFacadeLocal.class).count()); //invocation#2
}
@Override
@TransactionAttribute(TransactionAttributeType.NEVER)
public int count() {
return ((Long) q.getSingleResult()).intValue();
}
}
в 'invocation # 1' это Локальный вызов, не проходящий через прокси, он вернет счетчик
в 'invocation # 2' это вызов через прокси-сервер, и поэтому вы аннотируете его не поддерживать транзакцию, которая теперь открывается методом create (user), этот вызов вызовет исключение транзакции:
javax.ejb.EJBException: EJB нельзя вызвать в глобальной транзакции
Ответ 3
Они будут использовать ту же транзакцию.
Если я хорошо помню, транзакция запускается контейнером "до", метод вызывается и завершается после его завершения.
Поскольку "a" вызывает "b", "b" будет использовать ту же транзакцию.
: S
Я думаю, самое лучшее, что вы можете сделать, это проверить его, чтобы проверить его!:)