【问题标题】:How to handle JPA unique constraint violations?如何处理 JPA 唯一约束违规?
【发布时间】:2010-08-17 12:18:35
【问题描述】:

当违反唯一约束时,会抛出javax.persistence.RollbackException。但是可能有多种原因要抛出RollbackException。如何发现违反了唯一约束?

try {
    repository.save(article);
}
catch(javax.persistence.RollbackException e) {
    // how to find out the reason for the rollback exception?
}

【问题讨论】:

    标签: java exception jpa exception-handling constraints


    【解决方案1】:

    这对你来说可能很晚,但这是我为 PostGres 解决的方法。

    catch (DataIntegrityViolationException e) {
    
                for (Throwable t = e.getCause(); t != null; t = t.getCause()) {
    
                    if (PSQLException.class.equals(t.getClass())) {
                        PSQLException postgresException = (PSQLException) t;
    
                        // In Postgres SQLState 23505=unique_violation
                        if ("23505".equals(postgresException.getSQLState())) {
                            throw new CustomDataAlreadyExistsException("YourErrorCode", e);
                        }
                    }
                }
                throw new SomeOtherException("YourErrorCode2", e);
    
            }
    

    【讨论】:

      【解决方案2】:

      您可以使用以下内容:

      如果您使用的是 spring 框架,那么您可以使用:

      org.springframework.dao.DataIntegrityViolationException

      如果可以使用标准 JPA 以下

      org.hibernate.exception.ConstraintViolationException

      可以在 sql 级别使用以下内容:

      java.sql.SQLIntegrityConstraintViolationException

      【讨论】:

      • 它没有帮助我。可以确认一次吗?
      • 你不能谈论“标准 JPA”和提到休眠。
      【解决方案3】:

      如何发现违反了唯一性约束?

      异常是链式的,您必须递归调用getCause() 以获取特定于提供程序的异常(并且可能转到SQLException)以将其转换为您的应用程序可以为您的用户很好地处理的东西。以下将打印异常链:

      for (t = e.getCause(); t != null; t = t.getCause()) {
          logger.debug("Exception:" + t);
      }
      

      对于异常处理和“翻译”,您可以做类似 Spring 所做的事情(请参阅各种 JpaDialect 类,例如 HibernateJpaDialect 了解一下)。

      这一切都不好,这段代码不能移植,而且要找到导致违规的属性也不容易。这以某种方式确认没有elegant and portable way to handle constraint violations in JPA

      【讨论】:

        【解决方案4】:

        编译器在尝试违反唯一约束时返回异常 SQLIntegrityConstraintViolationException

        使用以下 catch 块概念来处理适当的异常。

        catch(SQLIntegrityConstraintViolationException e) 
        {
          // Error message for integrity constraint violation
        }
        catch(Exception e)
        {
         // Other error messages
        }
        

        【讨论】:

          【解决方案5】:

          使用e.getCause() 检查导致回滚的原因。

          【讨论】:

          • ...然后解析getCause().getMessag()?
          • 这取决于你会得到什么异常。如果是SQLException,,请检查错误和 SQLStatus。但是像 Spring 这样的一些框架将这些转换为更有意义的东西 (DataIntegrityViolationException)。
          【解决方案6】:

          我认为打印堆栈跟踪将帮助您了解这一点。 e.printStackTrace();

          【讨论】:

            【解决方案7】:

            你可以这样做:

            StringWriter writer=new StringWriter(); //remains the message from stack trace.
            e.printStackTrace(new PrintWriter(writer));
            String message=writer.toString(); // gets the message of full stack trace.
            

            然后查看异常信息。

            【讨论】:

            • 好的,但是我应该如何处理 StackTrace?用堆栈跟踪解析字符串有点难看,但也许是唯一的可能性。
            • 我怎么知道是哪个字段导致了约束违规?
            【解决方案8】:

            您必须捕获 javax.persistence.PersistenceException。 抛出的异常是 org.hibernate.exception.ConstraintViolationException。

            异常消息:org.hibernate.exception.ConstraintViolationException:密钥“nic_account_no”的重复条目“893073116V-1234567”

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-06-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-11-29
              • 1970-01-01
              相关资源
              最近更新 更多