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

2022-09-01 15:44:18

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

public Optional<T> get(Long id) {

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

当找不到任何东西时,我期待一个但实际上什么都没有。如果我检查我的结果,我可以看到我有一个空实体,其中有一个处理程序链接到它“扔了”,但我们没有进入捕获,我返回这个奇怪实体的可选。getOne(…)EntityNotFoundExceptionEntityNotFoundException

我无法理解这种行为。


答案 1

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

解决此问题的最简单方法是简单地使用,如下所示 。 如果未找到任何结果,将返回。findOne(…)Optional.ofNullable(repository.findOne(…))findOne(…)null

解决此问题的一种更高级方法是使存储库直接返回实例。这可以通过创建自定义基本存储库接口来实现,该接口使用 -methods 的返回类型。OptionalOptional<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> { … }

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


答案 2

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


这就是它对我的工作方式

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

推荐