![](/img/trans.png)
[英]EJB Dependencies are not wired (injected) properly on GlassFish 2.1
[英]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.