Spring JPA 仓库无法捕获 EntityNotFoundException。

10

当用户使用无效的ID搜索我的仓库时,我希望能够抛出自定义错误类。这应该很简单,但是我似乎无法捕获JpaRepository抛出的任何错误。我已经尝试了几次解决这个问题,但以下是我最直接的尝试:

try {
    Object obj = repository.getOne(id)
}
catch (EntityNotFoundException e) {
    throw CustomException("message");
}

在调试器中运行时,repository抛出了我期望的确切异常javax.persistence.EntityNotFoundException,但代码却简单地跳过了我的catch语句并返回一个错误。我尝试使用类似的结果来使用repository.findById(id),也尝试捕获ExceptionThrowable。有什么想法吗?如果我的问题不是立即明显的,我会在我的帖子中添加更多信息。

我也遇到了同样的问题!我不明白为什么它会这样行为,为什么会跳过catch :( - dk7
4个回答

12

getOne()EntityManager.getReference()的一个包装器,该方法不会抛出任何异常。

它返回一个未初始化的代理对象,假设实体确实存在。它不从数据库获取实体状态,因此甚至不知道它是否存在。它假设存在。

只有在尝试访问实体状态时,您才会在以后收到异常。

使用findById()/findOne(),检查是否获得非空/非null结果(因为这些方法如果实体不存在就不会抛出任何异常,它们会返回空或null),如果是这种情况,则抛出异常。


1
你可以尝试以下方法:
try {
    Object obj = repository.findById(id).orElseThrow(EntityNotFoundException::new);
}
catch (EntityNotFoundException e) {
    throw CustomException("message");
}

1
欢迎来到SO。虽然我们感谢您的回答,但如果它提供了其他答案所没有的附加价值,那将更好。在这种情况下,您的答案并未提供额外的价值,因为@JB Nizet已经发布了该解决方案。如果以前的答案对您有帮助,您应该在获得足够的声望后投票支持它 - Antoine

0
你需要在你的仓库类上加上@Repository注解,以便将异常包装成特定的持久化异常。
至于问题,你不需要使用getOne()方法来处理潜在的异常,而是可以使用一些其他的方法,比如findById()或者其他返回Optional<>对象的方法,在实体不存在的情况下不会抛出错误。

这是正确的。我必须用Optional<>包装我的响应。对于一个C++程序员来说,这是违反直觉的。谢谢! - Keifer

-1

你可以捕获 DataAccessException 而不是 EntityNotFoundException

try {
    Object obj = repository.getOne(id)
}
catch (DataAccessException e) {
    throw CustomException("message");
}

这个不起作用。请查看@JB Nizet的答案。当实体未被找到时,getOne(id)不会立即抛出任何异常。 - Sajib Acharya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接