Resolvi a minha necessidade, não sei se é a melhor forma mas deixo como fiz. Pode ajudar a alguem.
Pelo que pude entender pelas pesquisas que fiz na internet, o JPA embrulha as exceções em uma PersistenceException.
Dessa forma, no Spring e no controle global de exceções, desembrulhei as exceções. Durante o processo de desembrulhar eu verifico se é uma ConstraintViolationException, se for, faço um casting para poder pegar o retorno do método getConstrainName.
for(Throwablet=ex.getCause(); t != null; t = t.getCause()) {if(tinstanceofConstraintViolationException){
ConstraintViolationExceptions=(ConstraintViolationException)t;returnhandleExceptionInternal(ex,"Verifique o campo ["+s.getConstraintName()+"]. Este campo pode ser inválido ou já estar em uso.",newHttpHeaders(),HttpStatus.CONFLICT,request);}
}
returnhandleExceptionInternal(ex,ex.getMessage(),newHttpHeaders(),HttpStatus.CONFLICT,request);