我目前正致力于从输入文件中自动执行订阅流程的工作。
所以我有一个班级:
@Startup
@Singleton
public class ImportSubscriptionsJob implements Job {
//calls ImportSubscriptionsJobBean
}
Singleton类调用无状态类:
@Stateless
public class ImportSubscriptionsJobBean {
@PersistenceContext
private EntityManager em;
//we need a transaction
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@Interceptors({ JobLoggingInterceptor.class })
public void execute() {
//calls another stateless class with em injected
}
}
这个类调用另一个无状态类,依此类推。由于循环依赖性,某些类使用@LocalBean注释,因此需要通过以下方式注入:@EJB。
entityManager从第2级传递到第n。
现在的问题是在第n级服务调用,我遇到下面的错误。这是层次结构:
Singleton [1] - >无状态(TX = REQUIRES_NEW)[2] - >无状态 (TX = REQUIRES_NEW)[3] - >无国籍[4] - >无状态[5] - >无国籍[6] - >无国籍[7]
在第6级,它调用7级的方法,只需查询entityX:
List<X> Xs = getQuery(em).getResultList();
那就是抛出错误的时候。
有什么想法吗?
来自堆栈跟踪的最后一组行:
Caused by: org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessions
at org.hibernate.proxy.AbstractLazyInitializer.setSession(AbstractLazyInitializer.java:123) [hibernate-core-4.2.7.SP1-redhat-3.jar:4.2.7.SP1-redhat-3]
at org.hibernate.engine.internal.StatefulPersistenceContext.reassociateProxy(StatefulPersistenceContext.java:629) [hibernate-core-4.2.7.SP1-redhat-3.jar:4.2.7.SP1-redhat-3]
at org.hibernate.engine.internal.StatefulPersistenceContext.reassociateIfUninitializedProxy(StatefulPersistenceContext.java:588) [hibernate-core-4.2.7.SP1-redhat-3.jar:4.2.7.SP1-redhat-3]
at org.hibernate.event.internal.ProxyVisitor.processEntity(ProxyVisitor.java:49) [hibernate-core-4.2.7.SP1-redhat-3.jar:4.2.7.SP1-redhat-3]
请注意,我的交易是容器管理,所以我想知道为什么我收到此错误: - ?
如果我在第一个无状态课程中只保留一个REQUIRES_NEW,那我就得到了:
JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
但是为什么我的所有课程都使用无状态注释?默认情况下,它是一个会话bean,如果不存在,所有方法都可以启动一个新的tx。
答案 0 :(得分:1)
问题在于:
Stateless (TX=REQUIRES_NEW)[2]->Stateless (TX=REQUIRES_NEW)
如果您有2个REQUIRES_NEW,那么在您的流程中将会打开两个事务,并且您可能将同一个实体与两个并发会话相关联。
尝试将事务传播更改为REQUIRES。
从事务管理的角度来看,有状态EJB和无状态EJB之间的唯一区别是当您在有状态EJB字段中有实体引用时,或者当您使用扩展持久性上下文时。在这种情况下,将这两者混合起来要困难得多。从有状态的EJB调用无状态EJB时,您需要将实体作为方法参数传递给它。
至于交易传播,我认为没有理由不为所有此类电话使用相同的交易。事实上,这对于拥有一个单一的原子工作单元是强制性的。