У меня есть bean без состояния что-то вроде:
@Stateless
public class MyStatelessBean implements MyStatelessLocal, MyStatelessRemote {
@PersistenceContext(unitName="myPC")
private EntityManager mgr;
@TransationAttribute(TransactionAttributeType.SUPPORTED)
public void processObjects(List<Object> objs) {
// this method just processes the data; no need for a transaction
for(Object obj : objs) {
this.process(obj);
}
}
@TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
public void process(Object obj) {
// do some work with obj that must be in the scope of a transaction
this.mgr.merge(obj);
// ...
this.mgr.merge(obj);
// ...
this.mgr.flush();
}
}
Как правило, тогда клиент использует функцию processObjects (...), которая фактически не взаимодействует с менеджером сущностей. Он делает то, что ему нужно, и вызывает process (...) индивидуально для каждого объекта для обработки. Длительность процесса (...) относительно короткая, но для выполнения processObjects (...) может потребоваться очень много времени. Поэтому я не хочу поддерживать открытую транзакцию. Мне do нужны отдельные операции процесса (...) для работы в пределах их собственной транзакции. Это должна быть новая транзакция для каждого звонка. Наконец, я бы хотел оставить опцию открытой, чтобы клиент мог напрямую вызывать процесс (...).
Я пробовал несколько разных типов транзакций: никогда, не поддерживается, поддерживается (для processObjects) и требуется, требует нового (on process), но я получаю TransactionRequiredException при каждом вызове merge ().
Мне удалось заставить его работать, разделив методы на две разные компоненты:
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
@EJB
private MyStatelessBean2 myBean2;
public void processObjects(List<Object> objs) {
// this method just processes the data; no need for a transaction
for(Object obj : objs) {
this.myBean2.process(obj);
}
}
}
@Stateless
public class MyStatelessBean2 implements MyStatelessLocal2, MyStatelessRemote2 {
@PersistenceContext(unitName="myPC")
private EntityManager mgr;
@TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
public void process(Object obj) {
// do some work with obj that must be in the scope of a transaction
this.mgr.merge(obj);
// ...
this.mgr.merge(obj);
// ...
this.mgr.flush();
}
}
но мне все еще любопытно, возможно ли сделать это в одном классе. Мне кажется, что менеджер транзакций работает только на уровне компонентов, даже когда отдельным методам даются более конкретные аннотации. Поэтому, если я помечу один метод таким образом, чтобы транзакция не начала вызывать другие методы в этом же экземпляре, это также не приведет к созданию транзакции, независимо от того, как они помечены?
Я использую JBoss Application Server 4.2.1.GA, но неспецифичные ответы приветствуются / предпочтительны.