如何在Spring Data JPA中使用getOne()方法捕获IdentyNotFoundException?

nwwlzxa7  于 2023-10-19  发布在  Spring
关注(0)|答案(2)|浏览(159)

我需要知道如何用getOne()方法捕获EntityNotFoundException
我知道你会建议我使用像findById()findOne()这样的方法,它们检索的是真实的实体,而不是代理对象。
但在我的例子中,在插入对象之前,我有两个外键要设置。如果我使用一个以“find*”开头的方法,你可以清楚地看到,为了获取这些实体,会有冗余的数据库调用。
但据我所知,借助于这个从getOne()方法返回的代理对象,我可以用一个插入查询来执行这个操作。
所以现在的问题是,在传递给getOne()方法的外键无效的情况下,我需要通过捕获EntityNotFoundException来向最终用户发送错误响应,说明插入的外键无效。
我如何才能做到这一点?

5vf7fwbs

5vf7fwbs1#

如果插入操作由于无效的外键而失败,那么hibernate将抛出org.hibernate.exception.ConstraintViolationException,它在内部具有导致此异常的DB约束的名称。然后,您可以使用它来确定是哪个外键导致了此错误。
请注意,Spring可能会使用自己的Exception对象 Package 此异常,因为它具有持久性异常转换功能。这意味着在捕捉到spring-data抛出的异常后,可能需要遍历异常的因果链来找出ConstraintViolationException。我通常用Guava来做。Something like:

try{
  repository.saveAndFlush(employee);
} catch (Exception ex){
     Set<String> violateConstraintNames= Throwables.getCausalChain(ex).stream()
       .filter(e -> e instanceof ConstraintViolationException)
       .map(e -> (ConstraintViolationException) e)
       .map(ConstraintViolationException::getConstraintName)
       .collect(toSet());

     if(violateConstraintNames.contain("employee_department_fk")){
         throw new RuntimeException("Department does not exist");
     }else if (violateConstraintNames.contain("employee_manager_fk")){
         throw new RuntimeException("Manager does not exist");
     }else{
         throw ex;
     }
}

与使用findById()获取和检查引用的对象是否有效相比,代码看起来很难看。它还将DB实现细节(即外键的名称)泄漏到代码中,这是我会避免的。你是对的,它将引入额外的选择SQL,但我认为这是过早的优化,因为通过ID选择应该非常快,这要归功于数据库索引。同样,在重要的应用程序中,您迟早会发现必须获取这些引用对象以检查它是否通过某些业务规则,这是非常常见的。

exdqitrt

exdqitrt2#

我知道这个问题今天已经很老了,但在这种情况下,你必须捕获JpaObjectRetrievalFailureException而不是EntityNotFoundException

相关问题