Hibernate:2个会话上的非法代理关联

时间:2014-12-17 04:00:00

标签: hibernate java-ee jpa transactions stateless-session-bean

我目前正致力于从输入文件中自动执行订阅流程的工作。

所以我有一个班级:

@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。

1 个答案:

答案 0 :(得分:1)

问题在于:

Stateless (TX=REQUIRES_NEW)[2]->Stateless (TX=REQUIRES_NEW)

如果您有2个REQUIRES_NEW,那么在您的流程中将会打开两个事务,并且您可能将同一个实体与两个并发会话相关联。

尝试将事务传播更改为REQUIRES。

从事务管理的角度来看,有状态EJB和无状态EJB之间的唯一区别是当您在有状态EJB字段中有实体引用时,或者当您使用扩展持久性上下文时。在这种情况下,将这两者混合起来要困难得多。从有状态的EJB调用无状态EJB时,您需要将实体作为方法参数传递给它。

至于交易传播,我认为没有理由不为所有此类电话使用相同的交易。事实上,这对于拥有一个单一的原子工作单元是强制性的。