为什么Spring数据存储库上的getOne(…)不会抛出EntityNotFoundException?

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

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

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

我无法理解这种行为。

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

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

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

 interface BaseRepository extends Repository { Optional findOne(ID id); // declare additional methods if needed } interface YourRepository extends BaseRepository { … } 

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

这就是它对我有用的方式

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