Pergunta

I´m working on a project using Spring Data-JPA. I need to handle some exceptions in JpaRepository method calls.

In the code bellow, I need to intercept primary key violations erros but I cannot catch the exception directly. In my case, when an exception of this kind occurs, the UnexpectedRollbackException exception is thrown by repository layer (JpaRepository). I need to search inside this exception object to determine what is the cause of the problem.

I am wondering if there is a more "elegant" way to achieve this.

public Phone insert(Phone phone) throws BusinessException {
    Phone result = null;
    try{
        result = phoneRepository.save(phone);
    }
    catch(UnexpectedRollbackException ex){
        if((ex.getCause() != null && ex.getCause() instanceof RollbackException) &&
           (ex.getCause().getCause() != null && ex.getCause().getCause() instanceof PersistenceException) && 
           (ex.getCause().getCause().getCause() != null && ex.getCause().getCause().getCause() instanceof ConstraintViolationException)){
                throw new BusinessException("constraint violation", ex);
        }
    }
    catch(Exception ex){
        throw new OuvidorNegocioException("unknown error", ex);
    }       
    return result;
}

Thanks!

UPDATE:

The code bellow seems to be much better.

public Phone insert(Phone phone) throws BusinessException {
    Phone result = null;
    try{
        result = phoneRepository.save(phone);
    }
    catch(UnexpectedRollbackException ex){
        if(ex.getMostSpecificCause() instanceof SQLIntegrityConstraintViolationException){
                throw new BusinessException("constraint violation", ex);
        }
    }
    catch(Exception ex){
        throw new OuvidorNegocioException("unknown error", ex);
    }       
    return result;
}
Foi útil?

Solução

Wherever you handle the exception, you have the option of looking into the getMostSpecificCause() or getRootCause() methods of UnexpectedRollbackException. Here is information about those methods.

Outras dicas

As with others who have commented on your question — I, too, think the solution you have in your post is a bad one. The sole purpose of a repository abstraction is to hide away the persistence mechanism so that clients don't have to know about it. In your case you look for a low-level SQL Exception which has been intentionally abstracted away by Spring as well as JPA.

If you really want to handle a constraint violation, the DataIntegrityViolationException is the correct one to catch. The repositories will wrap the store specific (MongoDB, JPA, whatever you use) in Spring DataAccessException subtypes to allow the clients to do exactly that: catch an exception per error type, not per persistence mechanism.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top