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
Why does getOne(…) on a Spring Data repository not throw an EntityNotFoundException?
提问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 EntityNotFoundException
but 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 null
in 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 Optional
instances 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 @Repository
classes, 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);
}