【问题标题】:Why does getOne(…) on a Spring Data repository not throw an EntityNotFoundException?为什么 Spring Data 存储库上的 getOne(...) 不会抛出 EntityNotFoundException?
【发布时间】:2015-11-22 17:51:14
【问题描述】:

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

public Optional<T> get(Long id) {

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

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

我无法理解这种行为。

【问题讨论】:

  • 你为什么期待一个例外? javadoc 没有提到异常。
  • 当您在不存在的数据上调用 getOne() 时,这是经典的 JPA 行为。
  • 此外,我可以看到这个异常被抛出但以某种方式被spring数据处理?

标签: java spring jpa spring-data spring-data-jpa


【解决方案1】:

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

解决此问题的最简单方法是简单地使用findOne(…),例如Optional.ofNullable(repository.findOne(…))。如果没有找到结果,findOne(…) 将返回 null

解决此问题的更高级方法是使存储库直接返回 Optional 实例。这可以通过使用Optional&lt;T&gt; 作为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 examples repository 中找到完整的示例。

【讨论】:

  • 看起来是个好主意!我会马上试一试但是......性能怎么样,findOne 和 getOne 一样好吗?
  • 确实存在差异,因为getOne(…) 不会立即实现对象,而findOne(…) 会。前者的缺点是它也延迟了查找失败,这让你很痛苦。此外,findOne(…) 将访问EntityManager 中的一级缓存,因此在特定会话中,您不会两次访问数据库。如果这真的成为一个问题,你可能想明确插入一个缓存,但我会推迟到测量真正显示出来,那就有问题了。
  • 值得注意的是,截至 2019 年,CrudRepository 已经带来了 Optional&lt;T&gt; findById(ID id);,这与 2015 年这个答案所建议的差不多......
【解决方案2】:

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


这对我来说是这样的

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

【讨论】:

    猜你喜欢
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 2018-09-21
    相关资源
    最近更新 更多