Java JPA在ejb容器中引发了哪些异常?

Java JPA在ejb容器中引发了哪些异常?,java,jpa,jakarta-ee,ejb-3.0,Java,Jpa,Jakarta Ee,Ejb 3.0,我正在开发一个运行在glassfish v3上的EJB应用程序。如果我查看EntityManager类的javadoc,它会说find、persist等方法会抛出从PersistenceException派生的异常。然而,在实践中,我注意到,如果数据库级别出现问题(例如,找不到表),可以抛出从org.eclipse.persistence.exceptions.DatabaseException派生的异常。因此,我正确地假设,除了标准的持久性异常之外,我还必须处理由我使用的持久性提供程序引发的异

我正在开发一个运行在glassfish v3上的EJB应用程序。如果我查看EntityManager类的javadoc,它会说find、persist等方法会抛出从PersistenceException派生的异常。然而,在实践中,我注意到,如果数据库级别出现问题(例如,找不到表),可以抛出从org.eclipse.persistence.exceptions.DatabaseException派生的异常。因此,我正确地假设,除了标准的持久性异常之外,我还必须处理由我使用的持久性提供程序引发的异常?这往往意味着我需要编写特定于我选择的JPA提供程序的错误代码,如果我以后更改为其他提供程序,我需要更改代码以捕获不同的异常类,例如HibernateeException。

在我看来,您应该只处理标准JPA异常层次结构中的异常(除非您想处理规范中没有标准异常的特定情况,在这种情况下,您的应用程序将不可移植——但我想不出任何异常)。EJB 3.0 JPA规范(JSR 220)在第3.7节中对其进行了总结:

3.7例外情况概述 以下是报告的摘要 本协议定义的例外情况 规格:

PersistenceException

将抛出
PersistenceException
当 出现问题。可能是 抛出以报告调用 操作无法完成,因为 发生意外错误(例如,故障 要打开的持久性提供程序的 数据库连接)。
所有其他 本协议定义的例外情况 规范是
PersistenceException
。所有实例 of
PersistenceException
除了
NoResultException
不一致查询结果异常
将导致 当前事务(如果有) 活动,要标记为回滚

TransactionRequiredException

TransactionRequiredException为 由持久性提供程序引发 当交易是必需的,但 不活跃

OptimisticLockException

OptimisticLockException
为 由持久性提供程序引发 当乐观锁定发生冲突时 发生。可能会引发此异常 作为API调用的一部分,在刷新时,或 在提交时。当前 如果事务处于活动状态,则将 标记为回滚

RollbackException

RollbackException
由 持久性提供程序在
EntityTransaction.commit
失败

EntityExistsException

可能会引发
EntityExistsException
当 调用每个sist操作,并且 实体已存在。该 可能会引发EntityExistsException 调用persist操作时, 或
实体存在异常
或 另一个
PersistenceException
可能是 在提交时抛出

EntityNotFoundException

EntityNotFoundException
为 由持久性提供程序引发 当实体引用通过以下方式获得时:
getReference
已被访问,但 实体不存在。它也是 刷新操作在 该实体不再存在于中 数据库。当前事务,如果 一个处于活动状态,将被标记为 回滚

NoResultException

NoResultException
由 持久性提供程序在
Query.getSingleResult
被调用并 没有要返回的结果。此 异常不会导致当前错误 如果事务处于活动状态,则将 标记为回滚

ununiqueresultexception

ununiqueresultexception
为 由持久性提供程序引发 当
Query.getSingleResult
为 调用,并且有多个 查询的结果。此异常 不会引起电流 如果事务处于活动状态,则将 标记为回滚


对我来说,特定于提供程序的异常通常是“内部”的东西,用于指示技术问题,即应用程序中应该修复的bug(例如,如果缺少一个表,这是一个bug,修复它,处理这种异常是没有意义的).

这就是Spring框架将特定于实现的异常转换为独立于实现的异常的一般原因异常类型您可以在持久性层中编写异常代理代码,以捕获
数据库异常
,并重新播放您自己的
ShanesPersistenceException extends RuntimeException
(或其他)将原始异常作为原因包括在内。然后,如果以后切换实现,只需点击异常代理即可添加捕获并重新捕获新供应商的异常。

我对此做了一些实验。当切换到Hibernate时,我发现如果在调用EntityManager方法作为一个可丢弃的方法,如果发生了PersistenceException子类支持的情况之外的事情(例如缺少一个表)然后HibernateeException被包装在一个简单的持久性异常中,这是有意义的。如果你想知道持久性是否出了问题,你可以捕获PersistenceException

在TopLink案例中,我直接收到Eclipse DatabaseException。这对我来说似乎是一个bug——正如Pascal所提到的,应该没有必要捕捉特定于提供者的异常。我将为Glassfish制作一个bug报告