EJB-транзакции в локальных вызовах методов - PullRequest
20 голосов
/ 09 января 2009

В следующих настройках метод B выполняется в (новой) транзакции?

EJB, имеющий два метода, метод A и метод B

public class MyEJB implements SessionBean
    public void methodA() {
       doImportantStuff();
       methodB();
       doMoreImportantStuff();
    }

    public void methodB() {
       doDatabaseThing();
    }
}

EJB управляется контейнером, метод methodB - в транзакции 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 вызывать метод A с вызовом метода EJB. methodA теперь выполняется в транзакции. Будет ли последующий вызов methodB из methodA выполняться в той же транзакции или в новой транзакции? (обратите внимание, это фактический код здесь. Нет явного вызова ejb для метода B)

Ответы [ 3 ]

35 голосов
/ 09 января 2009

Ваш вызов methodB() - это обычный вызов метода, не перехваченный контейнером EJB; во время выполнения контейнер EJB внедрит прокси , а не экземпляр вашего класса, так он перехватывает вызовы и настраивает среду перед вызовом вашего метода. Если вы используете this, вы вызываете метод напрямую, а не через прокси. Следовательно, оба метода будут использовать одну и ту же транзакцию, независимо от того, что определено в ejb-jar.xml для вызовов через интерфейсы EJB.

23 голосов
/ 08 сентября 2012

введите 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 голосов
/ 09 января 2009

Они будут использовать одну и ту же транзакцию.

Если я хорошо помню, транзакция запускается контейнером «до», метод вызывается и фиксируется после его «завершения».

Поскольку «a» вызывает «b», «b» будет использовать ту же транзакцию.

: S

Полагаю, лучшее, что вы можете сделать, это проверить это! :)

...