如何处理JPA唯一约束违规?

当违反唯一约束时,抛出javax.persistence.RollbackException 。 但抛出RollbackException可能有多种原因。 如何才能发现违反了一个独特的约束?

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

如何才能发现违反了一个独特的约束?

exception是链接的,你必须递归调用getCause()以获取提供者特定的exception(并且可能转到SQLException )将其转换为应用程序可以很好地为您的用户处理的内容。 以下将打印exception链:

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

对于exception处理和“翻译”,您可以执行类似Spring的操作(请参阅各种JpaDialect类,例如HibernateJpaDialect以获得一个想法)。

所有这些都不好,这段代码不可移植,找到导致违规的属性并不容易。 这在某种程度上证实了在JPA中没有优雅且可移植的方式来处理约束违规 。

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

编译器在尝试违反唯一约束时返回exceptionSQLIntegrityConstraintViolationException

使用以下catch块概念来处理正确的exception。

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

您可以使用以下内容:

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

org.springframework.dao.DataIntegrityViolationException

如果可以使用标准JPA以下

org.hibernate.exception.ConstraintViolationException

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

java.sql.SQLIntegrityConstraintViolationException

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

你可以这样做:

 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. 

然后查看exception信息。

这可能对你来说很晚,但这是我为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); }