JPA在ejb容器中抛出了哪些异常?

时间:2010-03-07 02:00:11

标签: java jpa java-ee ejb-3.0

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

3 个答案:

答案 0 :(得分:6)

在我看来,你应该只处理标准JPA异常层次结构中的异常(除非你想处理规范没有标准异常的特定情况,在这种情况下你的应用程序不会便携式 - 但我想不出任何问题。 EJB 3.0 JPA规范(JSR 220)在3.7节中总结了它们:

  

3.7例外摘要

     

以下是摘要   由此定义的例外   规格:

     

PersistenceException

     

抛出PersistenceException   由持久性提供者提供的时候   出现问题。它可能是   抛出报告调用   操作无法完成,因为   意外错误(例如,失败   持久性提供程序打开一个   数据库连接)   所有其他   由此定义的例外   规范是。的子类   PersistenceException。所有实例   PersistenceException除外   NoResultException和。{的实例   NonUniqueResultException会导致   当前的交易,如果是的话   有效,标记为回滚。

     

TransactionRequiredException

     

TransactionRequiredException是   由持久性提供程序抛出   当需要交易但是   不活跃。

     

OptimisticLockException

     

OptimisticLockException是   由持久性提供程序抛出   当一个乐观的锁定冲突   发生。可能会抛出此异常   作为API调用的一部分,在flush,或   在提交时。目前   交易,如果一个是活跃的,将是   标记为回滚。

     

RollbackException

     

RollbackException被抛出   持久性提供者何时   EntityTransaction.commit失败。

     

EntityExistsException

     

EntityExistsException可能会抛出   由持久性提供者提供的   调用perist操作和   实体已经存在。该   可能会抛出EntityExistsException   当调用持久化操作时,   或EntityExistsException或   另一个PersistenceException可能是   在提交时抛出。

     

EntityNotFoundException

     

EntityNotFoundException是   由持久性提供程序抛出   当获得的实体参考时   访问getReference但是   实体不存在。也是   刷新操作时抛出的   该实体不再存在于   数据库。当前的交易,如果   一个是活跃的,将被标记为   回滚。

     

NoResultException

     

NoResultException被抛出   持久性提供者何时   调用Query.getSingleResult并且   没有结果可以返回。这个   异常不会导致当前   交易,如果一个人是活跃的,那就是   标记为回滚。

     

NonUniqueResultException

     

NonUniqueResultException是   由持久性提供程序抛出   当Query.getSingleResult时   调用,并且有多个   查询的结果。这个例外   不会引起潮流   交易,如果一个人是活跃的,那就是   标记为回滚。

对我来说,特定于提供者的异常是“内部”的东西,大部分时间都用于表示技术问题,即应用程序中应该修复的错误(例如,如果缺少表,则是错误,修复它,它不会'有意义地处理这种异常)。

答案 1 :(得分:1)

我做了一些更多的实验。当我切换到Hibernate时,我发现如果我在bean中捕获异常调用EntityManager方法作为Throwable,那么如果发生的事情超出PersistenceException子类支持的情况(例如缺少一个表),那么HibernateException包含在一个普通的Persistence Exception中,这是有道理的。如果你想知道持久性是否出错,你可以捕获PersistenceException。

在TopLink的情况下,我直接收到了Eclipse DatabaseException。这对我来说似乎是个错误 - 正如Pascal所提到的,应该没有必要捕获提供者特定的异常。我将为Glassfish制作一个错误报告,并在此处发布一个指向结果的链接。

在这两种情况下,如果没有在EntityManager的站点上捕获异常,那么异常将被捕获并作为容器更常见的东西被重新抛出,例如EJBException或TransactionRolledBackException,并且在大多数情况下捕获这些异常更有意义。

答案 2 :(得分:0)

这通常是Spring框架将特定于实现的异常转换为与实现无关的异常的原因。如果您担心捕获“内部”异常类型的耦合,您可以在持久层中编写异常代理代码以捕获DatabaseException并重新抛出您自己的ShanesPersistenceException extends RuntimeException(或其他),并将原始异常包括在内原因。然后,如果您稍后切换实现,则只需触摸异常代理即可为新供应商的异常添加catch-and-rethrow。