这是因为你扔了一个RuntimeException来自 EJB。
当这样的RuntimeException
没有注释为@ApplicationException,然后 EJB 容器会将其包装在javax.ejb.EJBException
并重新抛出它。这样做是因为运行时异常是usually仅用于指示代码逻辑中的错误,即程序员的错误,而不是最终用户的错误。你知道,NullPointerException
, IllegalArgumentException
, IndexOutOfBoundsException
, NumberFormatException
和朋友。这允许 EJB 客户端对此类运行时异常有一个捕获点,例如catch (EJBException e) { There's a bug in the service layer or in the way how we are using it! }
如果你尝试过catch (Exception e)
并检查了实际的异常,那么您就会注意到这一点。
修复你的BusinessException
类相应地添加该注释,然后它将被识别为真正的应用程序异常,并且不会被包装在EJBException
:
@ApplicationException(rollback=true)
public class BusinessException extends RuntimeException {
// ...
}
请注意,如果您抛出非RuntimeException
,那么你仍然需要保留注释,明确地使用rollback=true
,因为默认情况下它不会执行回滚,与RuntimeException
没有注释。
@ApplicationException(rollback=true)
public class BusinessException extends Exception {
// ...
}
总结:
-
RuntimeException
从事务性 EJB 方法抛出的异常将执行完全回滚,但异常将被包装在EJBException
.
-
RuntimeException
with @ApplicationException
来自事务性 EJB 方法将仅在以下情况下执行完全回滚rollback=true
是明确设置的。
-
Exception
来自事务性 EJB 方法将不会执行完全回滚。
-
Exception
with @ApplicationException
来自事务性 EJB 方法将仅在以下情况下执行完全回滚rollback=true
是明确设置的。
注意@ApplicationException
继承自自定义异常的所有子类,因此您无需对所有子类重复它。最好的办法是将其作为抽象类。另请参阅下面链接的相关问题中的示例。
也可以看看:
- 让表示层(JSF)处理来自服务层(EJB)的业务异常