繁体   English   中英

GlassFish 2.1中的EJB TransactionRequiredException

[英]EJB TransactionRequiredException in GlassFish 2.1

在我的Stateful bean中,有以下几行:

@Stateful(mappedName = "ejb/RegistrationBean")
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 30)
@TransactionManagement(value=TransactionManagementType.CONTAINER)
public class RegistrationStateful implements RegistrationStatefulRemote {

    @PersistenceContext
    EntityManager em;

    private List<Event> reservedSessions = new ArrayList<Event>();
    private boolean madePayment = false;

    ...
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    private void cancelReservation() {
        if (reservedSessions.size() != 0) {
            Teacher theTeacher;
            for (Event session : reservedSessions) {
                if ((theTeacher = session.teacher) == null) theTeacher = bestTeacher.teacher;
                theTeacher = em.merge(theTeacher) //The exception is thrown here

                //Make changes to theTeacher

                em.flush(); //The exception is also thrown here
            }

            //Clear the reservedSessions list
            reservedSessions.clear();
        }
    }

    @Remove
    public void endRegistration() {}

    @PreDestroy
    public void destroy() {
        //Cancel outstanding reservations if payment has not been made
        if (!madePayment) cancelReservation(); 
    }
}

em.merge(someEntity)抛出TransactionRequiredException 有人可以告诉我为什么会发生吗? 我以为TransactionAttribute.REQUIRED ,如果没有活动的交易将自动创建一个交易。 我尝试使用em.joinTransaction()但是它抛出了相同的Exception 我是这笔交易的初学者。 如果有人可以向我解释一下,我将不胜感激。

更新:我想添加更多信息

实际上, Stateful Bean还具有以下功能:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
private void reserveSession(List<Event> sessions) throws ReservationException {
    //Reserve the sessions
    Teacher theTeacher;

    for (Event session : sessions) {
        if ((theTeacher = session.teacher) == null) theTeacher = bestTeacher.teacher;
        theTeacher = em.merge(theTeacher);

        //Make changes to theTeacher            

        em.flush();
    }   
}

流程如下:用户告诉我他的空闲时间,我为他保留了一些座位。 在那之后,我给他看他保留的座位,他可以选择付款或取消预定。

reserved()函数可以按预期完美运行,但cancelReservation()却没有。

更新2:昨晚我通过在“ cancelReservation()”函数中的“ @TransactionAttribute(TransactionAttributeType.REQUIRED)”,“ em.merge(theTeacher)”和“ em.flush()”两行中注释掉来解决此问题。 结果是完美的。 如果我切断那些线,那会安全吗? 我担心我一开始使用“ em.merge()”时会出现“分离实体”异常。

我唯一想到的(如果您要对双关语感到cancelReservation() )是,如果您正在从bean内的另一个方法调用cancelReservation() ,那么我不确定是否会遵守事务注释。 注释最终通过召唤拦截器起作用,我相信拦截器仅适用于不同类之间的调用(这是我应该真正检查的东西)。

因此,如果在Bean上有一个调用事务方法的非事务方法,那么在调用事务方法时就不会启动事务。

我对此可能完全错了。 我将去阅读一下规格,然后再回头给您。

编辑:我读了规范,它使我想起了J2EE规范是一个灾区。 太恐怖了 但是,有关事务的部分似乎暗示事务属性仅适用于对EJB业务接口的调用。 我相信,即使被调用的方法是该接口的一部分,从一个方法到bean内部的另一个方法的调用也不认为会通过业务接口。 因此,您不会期望它们吸引交易。

您可以尝试通过接口路由它们。 没有很好的方法可以做到这一点,但是您应该能够像这样注入业务接口自引用:

public class RegistrationStateful implements RegistrationStatefulRemote {
    @EJB
    private RegistrationStatefulRemote self;

然后,您可以将@PreDestroy方法更改为如下所示:

@PreDestroy
public void destroy() {
    self.cancelReservation();
}

而且我认为这应该算作正常的业务接口调用,事务处理等等。

我从来没有尝试过,所以这可能是完全垃圾。 如果您尝试一下,请告诉我它是如何工作的!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM