У меня есть безстоящий 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 (...), который фактически не взаимодействует с менеджером сущности. Он выполняет то, что ему нужно, и вызывает процесс (...) индивидуально для каждого обрабатываемого объекта. Продолжительность процесса (...) относительно короткая, но processObjects (...) может занять очень много времени, чтобы пробежать все. Поэтому я не хочу, чтобы он поддерживал открытую транзакцию. Мне нужны отдельные процессы (...) для работы в рамках их собственной транзакции. Это должна быть новая транзакция для каждого вызова. Наконец, я хотел бы оставить опцию открытой для того, чтобы клиент напрямую вызывал процесс (...).
Я пробовал несколько разных типов транзакций: никогда, не поддерживался, поддерживался (на processObjects) и требовался, требует новых (по процессу), но я получаю TransactionRequiredException каждый раз, когда вызывается merge().
Мне удалось заставить его работать, разделив методы на два разных beans:
@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();
}
}
но мне все еще интересно, если это возможно сделать в одном классе. Мне кажется, что диспетчер транзакций работает только на уровне bean, даже если отдельным методам даются более конкретные аннотации. Поэтому, если я помечу одному методу, чтобы предотвратить запуск транзакции другими методами внутри этого же экземпляра, также не будет создана транзакция, независимо от того, как они отмечены?
Я использую JBoss Application Server 4.2.1.GA, но неспецифические ответы приветствуются/предпочтительны.