如何处理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); }