在 JavaEE 无状态会话 bean 中,为什么 SessionContext 负责回滚事务而不是 EntityManager?
In a JavaEE stateless session bean, why is the SessionContext responsible for rolling transactions back and not the EntityManager?
对我(JavaEE 开发的新手)来说,我认为容器管理的 EntityManager 将负责回滚失败的事务,而不是 SessionContext 实例。假设以下场景...
@Stateless
public class MySessionBean implements MySessionBeanRemoteInterface {
@PersistenceContext(unitName="MYPu")
private EntityManager em;
@Resource
private SessionContext sctx;
@Override
public WhosebugUser createSOUser(String userName, int rep) {
try {
WhosebugUser su = new WhosebugUser();
su.setUserName(WhosebugName);
su.setRep(rep);
su.setIsBalusC(userName.equals("BalusC");
su.setIsTheJonSkeet(userName.equals("jon skeet"));
return em.merge(su);
} catch (Exception e) {
//sctx.setRollbackOnly();
return null;
}
}
}
为什么 EntityManager 不对此负责?为什么要使用 SessionContext?
因为您告诉容器通过 JTA (transaction-type="JTA"
) 而不是 JPA (transaction-type="RESOURCE_LOCAL"
) 管理事务。 JTA 又由 EJB 容器管理。因此 SessionContext
的作用在这里。
但令我困扰的是,您正在抑制异常并返回 null
。你最好不要在业务服务方法中这样做。你最好让异常消失而不是返回 null
。 EJB 容器将在任何异常情况下自动执行回滚。摆脱 EJB 中的 try-catch
和 return null
,让 EJB 的客户端自己处理异常。
例如
try {
mySessionBean.createSOUser(userName, rep);
} catch (PersistenceException e) {
showSomeGlobalErrorMessage(e.getMessage());
}
或者,更好的是,让它进一步深入底层容器。例如。如果它实际上是一个 servlet 容器:
<error-page>
<exception-type>javax.persistence.PersistenceException</exception-type>
<location>/WEB-INF/errorpages/db-fail.xhtml</location>
</error-page>
或者所讨论的 MVC 框架甚至有一个可定制的全局异常处理程序。至少,JSF 允许这个机会,然后您可以全局设置一个面孔消息,而无需在调用服务方法的托管 bean 方法中的所有地方重复 try-catch
。
另请参阅:
- Wikibooks - JPA - Transactions
- When is it necessary or convenient to use Spring or EJB3 or all of them together?
对我(JavaEE 开发的新手)来说,我认为容器管理的 EntityManager 将负责回滚失败的事务,而不是 SessionContext 实例。假设以下场景...
@Stateless
public class MySessionBean implements MySessionBeanRemoteInterface {
@PersistenceContext(unitName="MYPu")
private EntityManager em;
@Resource
private SessionContext sctx;
@Override
public WhosebugUser createSOUser(String userName, int rep) {
try {
WhosebugUser su = new WhosebugUser();
su.setUserName(WhosebugName);
su.setRep(rep);
su.setIsBalusC(userName.equals("BalusC");
su.setIsTheJonSkeet(userName.equals("jon skeet"));
return em.merge(su);
} catch (Exception e) {
//sctx.setRollbackOnly();
return null;
}
}
}
为什么 EntityManager 不对此负责?为什么要使用 SessionContext?
因为您告诉容器通过 JTA (transaction-type="JTA"
) 而不是 JPA (transaction-type="RESOURCE_LOCAL"
) 管理事务。 JTA 又由 EJB 容器管理。因此 SessionContext
的作用在这里。
但令我困扰的是,您正在抑制异常并返回 null
。你最好不要在业务服务方法中这样做。你最好让异常消失而不是返回 null
。 EJB 容器将在任何异常情况下自动执行回滚。摆脱 EJB 中的 try-catch
和 return null
,让 EJB 的客户端自己处理异常。
例如
try {
mySessionBean.createSOUser(userName, rep);
} catch (PersistenceException e) {
showSomeGlobalErrorMessage(e.getMessage());
}
或者,更好的是,让它进一步深入底层容器。例如。如果它实际上是一个 servlet 容器:
<error-page>
<exception-type>javax.persistence.PersistenceException</exception-type>
<location>/WEB-INF/errorpages/db-fail.xhtml</location>
</error-page>
或者所讨论的 MVC 框架甚至有一个可定制的全局异常处理程序。至少,JSF 允许这个机会,然后您可以全局设置一个面孔消息,而无需在调用服务方法的托管 bean 方法中的所有地方重复 try-catch
。
另请参阅:
- Wikibooks - JPA - Transactions
- When is it necessary or convenient to use Spring or EJB3 or all of them together?