即使声明了事务属性,也会发生TransactionRequiredException

时间:2017-09-14 10:39:43

标签: transactions ejb-3.1 jboss-eap-6

我正在使用JBOSS EAP 6.x.

我有ejb.method1(),其中注明了交易属性@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

来自ejb.method2()内部的

,其中使用事务属性@TransactionAttribute(TransactionAttributeType.SUPPORTS)

进行注释

我从ejb.method2()

致电ejb.method1()

如下所示

    ejb.method() {
        //some operation 
         ejb.method2();
        //some operation
    }

    ejb2.method2() {

        //some operation 

        merge(entity1); // no error here

        try {
           sendMessageToMQ // no error here} catch(Exception e) {
           entity.setStatus("SUCCESS");
        } catch() {Expcetion) {
           entity1.setStatus("ERROR");
        } finally {
           merge(entity1); // Throwing Caused by: javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context
        }
    }

如果执行在一分钟内完成,则代码可以正常工作,但是当它花费大约3分钟时,它会因以下异常而失败。事务超时设置为15分钟。

Caused by: javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context

2 个答案:

答案 0 :(得分:0)

在新方法中提取第二个合并方法并使用事务属性对其进行注释后,它对我有用。调用提取方法的方法已经使用Transaction Attribute Supports进行了注释。

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
ejb.method() {
    //some operation 
     ejb.method2();
    //some operation
}

@TransactionAttribute(TransactionAttributeType.SUPPORTS)
ejb2.method2() {
    //some operation 
    merge(entity1); // no error here
    try {
       sendMessageToMQ // no error here} catch(Exception e) {
       entity.setStatus("SUCCESS");
    } catch() {Expcetion) {
       entity1.setStatus("ERROR");
    } 
    thisService.updateMessageStatus(entity1);
}

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void updateMessageStatus(Entity entity) {
    merge(entity)
}

答案 1 :(得分:0)

在您的情况下,解决方案是将您的merge()方法包含在新交易中,例如:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public void updateMessageStatus(Entity entity) {
     merge(entity);
}

并且到处呼叫updateMessageStatus()而不是直接merge()


为什么您的代码有效?

@TransactionAttribute(REQUIRED)上的{p> updateMessageStatus()说"如果来电者没有任何交易,则创建一个新的"。 正如我在评论中所写,第一次交易在第一次调用合并后结束。在这一行之后:

merge(entity1); // no error here

当您致电updateMessageStatus()时,REQUIRED会打开一个新事务,并在updateMessageStatus()结束时提交/回滚。
您只是打开一个新的交易,因为您在第二次通话中没有任何有效的交易。这就是为什么我的建议是将updateMessageStatus()注释为REQUIRES_NEW

关于SUPPORTS的另一个观察是(假设您在ejb2.method2()内呼叫ejb.method()

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
ejb.method() {
     ejb2.method2();
}

@TransactionAttribute(TransactionAttributeType.SUPPORTS)
ejb2.method2() {
    thisService.updateMessageStatus(entity1);
}

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void updateMessageStatus(Entity entity) {

}
如果仅从@TransactionAttribute(SUPPORTS)调用该方法,

ejb2.method2()没有意义,因为ejb.method()已经有了一个事务。我会让默认的@TransactionAttribute(REQUIRED)