如何处理和解析 JPA 持久性异常,以便向用户提供有意义的消息

我对JPA相当陌生,希望在处理JPA的持久性异常时找到最佳实践,例如,用户可以解决的唯一约束冲突。关于如何编写JPA应用程序的例子很多,但几乎没有关于如何处理被他们踢出的异常。:/

例如,在注册用户时,此人输入了系统已在使用中的电子邮件地址,并收到约束冲突:

try {
     em.persist(credentials);
} catch (javax.persistence.PersistenceException ex) {

添加重复的电子邮件时,会产生此错误:

WARNING: SQL Error: 0, SQLState: 23505
SEVERE: ERROR: duplicate key value violates unique constraint "EMAIL_UQ_IDX"
  Detail: Key (email)=(testuser@xyz.com) already exists.

如何向用户返回有意义的答案?例如:哎呀,看起来有人已经在使用该电子邮件地址,您确定以前没有注册过吗?是否有内置工具来解析它,或者我是否需要对(可能是一系列)if语句中的异常消息运行正则表达式?

如果它被抓到业务层呢?将其提升到表示层的最佳实践是什么...就像我之前说的,这样就可以为用户提供一个“好”的消息。


为了清楚起见,补充一点:为了让人们知道,我曾经,拥有,并且仍在研究所有不同类型的持久性异常,以下是我一直在做的一些研究,我没有包括我上面包含的“try语句”示例:

try {
     em.persist(credentials);
     } catch (javax.persistence.PersistenceException ex) {
         System.out.println("EXCEPTION CLASS NAME: " + ex.getClass().getName().toString());
         System.out.println("THROWABLE CLASS NAME: " + ex.getCause().getClass().getName().toString());
                Throwable th = ex.getCause();
         System.out.println("THROWABLE INFO: " + th.getCause().toString());
         Logger.getLogger(CredentialsControllerImpl.class
              .getName()).log(Level.INFO, "Credentials Controller "
                  + "persistence exception "
                      + "EXCEPTION STRING: {0}", ex.toString());
         Logger.getLogger(CredentialsControllerImpl.class
              .getName()).log(Level.INFO, "Credentials Controller "
                  + "persistence exception "
                      + "THROWABLE MESSAGE: {0}", th.getMessage());
         Logger.getLogger(CredentialsControllerImpl.class
              .getName()).log(Level.INFO, "Credentials Controller "
                  + "persistence exceptions "
                      + "THROWABLE STRING: {0}", th.toString());
     }

:)


答案 1

通常不使用低级异常来执行此操作。

相反,您可以显式检查电子邮件是否可用(使用查询),并且仅当电子邮件不存在时才将其保留。

当然,如果两个线程并行执行相同的检查,则可能存在争用情况,但这种情况将非常罕见,并且数据库约束是为了保证唯一性。


答案 2

PersistenceException有子类:EntityExistsException,EntityNotFoundException,NonUniqueResultException,NoResultException,OptimisticLockException,RollbackException,TransactionRequiredException。资料来源:http://docs.oracle.com/javaee/5/api/javax/persistence/PersistenceException.html

您可以使用它们。尝试检查异常的类型或重载错误处理方法(这更好)。EntityExistsException 我认为您在上面给出的示例中搜索的错误。但是你应该自己检查“它是否存在”。这是最佳实践。

永远不需要向用户显示 SQL 错误。该错误始终适合您。任何需要通知用户的数据相关错误都必须手动检查。

我使用 J2EE Web Environment。我只是将请求转发给错误.jsp如果有异常。我还为错误提供了一个额外的对象.jsp来澄清诸如用户可以返回,可以在错误后转到哪个页面等信息。当然,我自动化了这一点,我不喜欢编写冗余代码,因为它很难更新。所以我只是将异常和错误消息写入 catch 块中的另一个类。


推荐