Java 如何在Spring数据JPA中使用getOne()方法捕获EntityNotFoundException?

Java 如何在Spring数据JPA中使用getOne()方法捕获EntityNotFoundException?,java,spring-boot,hibernate,jpa,spring-data-jpa,Java,Spring Boot,Hibernate,Jpa,Spring Data Jpa,我需要知道如何使用getOne()方法捕获EntityNotFoundException 我知道您会建议我使用像findById()或findOne()这样的方法来检索真实实体,而不是代理对象 但是在我的例子中,我有两个外键要在插入对象之前设置。因此,如果我使用以“find*”开头的方法来设置这些键,您可以清楚地看到将有冗余的数据库调用来获取这些实体 但是据我所知,借助于从getOne()方法返回的这个代理对象,我可以用一个insert查询执行这个操作 因此,现在的问题是,如果传递给getOne

我需要知道如何使用
getOne()
方法捕获
EntityNotFoundException

我知道您会建议我使用像
findById()
findOne()
这样的方法来检索真实实体,而不是代理对象

但是在我的例子中,我有两个外键要在插入对象之前设置。因此,如果我使用以“find*”开头的方法来设置这些键,您可以清楚地看到将有冗余的数据库调用来获取这些实体

但是据我所知,借助于从
getOne()
方法返回的这个代理对象,我可以用一个insert查询执行这个操作

因此,现在的问题是,如果传递给
getOne()
方法的外键无效,我需要通过捕获插入的外键无效的
EntityNotFoundException
向最终用户发送错误响应


如何实现这一点?

如果由于无效外键而导致插入失败,hibernate将抛出
org.hibernate.exception.ConstraintViolationException
,其内部具有导致此异常的DB约束的名称。然后,您可以使用它来确定是哪个外键导致它

请注意,Spring可能会使用它自己的异常对象包装此异常,因为它的。这意味着在捕捉到spring数据引发的异常后,您可能必须遍历异常的因果链,以找出
ConstraintViolationException
。我通常用它来做这件事。比如:

试试看{
repository.saveAndFlush(员工);
}捕获(例外情况除外){
设置violateConstraintNames=Throwables.getCausalChain(ex.stream)()
.filter(e->e ConstraintViolationException实例)
.map(e->(ConstraintViolationException)e)
.map(ConstraintViolationException::getConstraintName)
.收集(toSet());
如果(违反约束名称包含(“员工\部门\ fk”)){
抛出新的RuntimeException(“部门不存在”);
}否则(违反约束名称包含(“员工/经理”)){
抛出新的RuntimeException(“管理器不存在”);
}否则{
掷骰子;
}
}

在我看来,与使用
findById()
获取并检查引用对象是否有效相比,代码看起来很难看。它还将DB实现细节(即外键的名称)泄露给代码,这是我应该避免的。没错,它将引入额外的SELECT SQL,但我认为它是早熟的优化,因为ID的选择应该非常快,这得益于数据库索引。同样,在非平凡的应用程序中,您迟早会发现必须获取这些被引用的对象,以检查其是否通过了某些业务规则。

您可以构建一个包装器,该包装器接受供应商,并将供应商调用包装成一个try-catch。如果可以返回Id,则可以在可选字段中返回Id。异常时返回可选的.empty。如果从包装器中获得可选的空返回,则将消息返回给用户