java 为什么 Spring Data 存储库上的 getOne(...) 不会抛出 EntityNotFoundException?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32264758/
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-11-02 19:55:00  来源:igfitidea点击:

Why does getOne(…) on a Spring Data repository not throw an EntityNotFoundException?

javaspringjpaspring-dataspring-data-jpa

提问by Seb

I'm working on a weird issue, I was doing integration testing, calling my controller to get an object from database that doesn't exist.

我正在处理一个奇怪的问题,我正在做集成测试,调用我的控制器从数据库中获取一个不存在的对象。

public Optional<T> get(Long id) {

  try {
    return Optional.ofNullable(repository.getOne(id));
  } catch(EntityNotFoundException e) {
    return Optional.empty();
  }
}

When getOne(…)is not able to find anything, I was expecting an EntityNotFoundExceptionbut actually nothing. If I inspect my result I can see that I have an empty entity with a handler link to it "threw EntityNotFoundException" but we don't go in the catch and I return an optional of this weird entity.

getOne(…)无法找到任何东西时,我期待EntityNotFoundException但实际上什么都没有。如果我检查我的结果,我可以看到我有一个带有处理程序链接的空实体“抛出EntityNotFoundException”,但我们没有进入捕获状态,我返回了这个奇怪实体的可选。

I can't understand this behavior.

我无法理解这种行为。

回答by Oliver Drotbohm

This is due to the way JPA specifies EntityManager.getReference(…)to work. It's supposed to return a proxy that will either resolve the object to be returned on the first access of a property or throw the contained exception eventually.

这是由于 JPA 指定EntityManager.getReference(…)的工作方式。它应该返回一个代理,该代理将在第一次访问属性时解析要返回的对象,或者最终抛出包含的异常。

The easiest way to work around this is to simply use findOne(…)instead, like this Optional.ofNullable(repository.findOne(…)). findOne(…)will return nullin case no result is found.

解决这个问题的最简单方法是简单地使用findOne(…),就像这样Optional.ofNullable(repository.findOne(…))。如果未找到结果,findOne(…)将返回null

A more advanced way of resolving this is to make the repository return Optionalinstances directly. This can be achieved by creating a custom base repository interface using Optional<T>as return type for the find…-methods.

解决此问题的更高级方法是让存储库Optional直接返回实例。这可以通过使用-methods 的Optional<T>返回类型创建自定义基本存储库接口来实现find…

interface BaseRepository<T, ID extends Serializable> extends Repository<T, ID> {

  Optional<T> findOne(ID id);

  // declare additional methods if needed
}

interface YourRepository extends BaseRepository<DomainClass, Long> { … }

Find a complete example of this in the Spring Data examples repository.

Spring Data 示例存储库中找到一个完整的示例。

回答by VK321

In Spring @Repositoryclasses, the getOne(id)method doesn't always verify existence until the object is queried (by calling entity.getId()or something) so it's no-such-entity exception may be delayed. To validate right away, use findById(id)instead (which returns an Optional<EntityType>which will be empty if the entity with that id doesn't exist).

在 Spring@Repository类中,在getOne(id)查询对象(通过调用entity.getId()或其他方式)之前,该方法并不总是验证存在,因此它的无此类实体异常可能会延迟。要立即验证,请findById(id)改用(Optional<EntityType>如果具有该 id 的实体不存在,它将返回一个空值)。



This is how it worked for me

这就是它对我的工作方式

public User findUserById(Long id) {
    return userRepository.findById(id).orElse(null);
}