'How to get the constraint name in a org.springframework.dao.DataIntegrityViolationException?

In my application when a violation key is raised, I would like to get the constraint name, but I'm not finding any method to get this information. The message returned by "getMessage()" is very summarized and I need more information about the error to make a customizable error message to the end user.

The stack trace:

84732 [http-8080-1] WARN  org.hibernate.util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 23505
84732 [http-8080-1] ERROR org.hibernate.util.JDBCExceptionReporter  - ERROR: duplicate key value violates unique constraint "ix_tb_oferta_vaga"
  Detalhe: Key (cd_pj, cd_curso)=(680, 29) already exists.
187405 [http-8080-1] WARN  org.hibernate.util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 23505
187405 [http-8080-1] ERROR org.hibernate.util.JDBCExceptionReporter  - ERROR: duplicate key value violates unique constraint "ix_tb_oferta_vaga"
  Detalhe: Key (cd_pj, cd_curso)=(680, 29) already exists.

The getMessage():

could not insert: [br.gov.ce.seduc.estagio.model.bean.OfertaVaga]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [br.gov.ce.seduc.estagio.model.bean.OfertaVaga]

Thanks.

Arthur



Solution 1:[1]

Insert a catch statement like this:

catch (DataIntegrityViolationException e) {
        String message = e.getMostSpecificCause().getMessage();
}

Solution 2:[2]

If you are using PostgreSQL and you are really interested to find detailed cause of the exception, then you can use PostgreSQL in compilation time, as so:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <!--<scope>runtime</scope>-->
</dependency>

This way, you will have utility methods and the PSQLException class. With this, now you can cast most specific cause to it.

var exceptionCause = exception.getMostSpecificCause();

if (exceptionCause instanceof PSQLException psqlException) {
    var serverErrorMessage = psqlException.getServerErrorMessage();

    if (serverErrorMessage != null) {
        var detail = serverErrorMessage.getDetail();
        exceptionCause = new Exception(detail);
    }
}

As you can see, now you can throw or handle this exceptionCause that will have your detailed or human-readable message.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ishita Sinha
Solution 2 Cristóbal Gajardo Vera