Java Spring 数据异常处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21000110/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:50:40  来源:igfitidea点击:

Spring Data Exception Handling

javaspringspring-dataspring-data-jpa

提问by outlookrperson

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

我正在使用 Spring Data-JPA 进行一个项目。我需要处理 JpaRepository 方法调用中的一些异常。

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.

在下面的代码中,我需要拦截主键违规错误,但我无法直接捕获异常。就我而言,当发生此类异常时,存储库层 (JpaRepository) 会抛出 UnexpectedRollbackException 异常。我需要在这个异常对象中搜索以确定问题的原因。

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;
}

采纳答案by Vidya

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

无论您在哪里处理异常,您都可以选择查看 的getMostSpecificCause()getRootCause()方法UnexpectedRollbackException以下是有关这些方法的信息

回答by Oliver Drotbohm

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.

与对您的问题发表评论的其他人一样 - 我也认为您在帖子中提供的解决方案是一个糟糕的解决方案。存储库抽象的唯一目的是隐藏持久性机制,以便客户端不必知道它。在您的情况下,您会寻找已被 Spring 和 JPA 有意抽象掉的低级 SQL 异常。

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

如果您真的想处理违反约束的情况,那么DataIntegrityViolationException捕获是正确的。存储库将特定于存储(MongoDB、JPA,无论您使用什么)包装在 SpringDataAccessException子类型中,以允许客户端完全做到这一点:根据错误类型捕获异常,而不是根据持久性机制捕获异常。