Spring Data JPA findOne()更改为Optional如何使用?

Hul*_*hoi 43 java spring spring-data-jpa

我正在学习SpringBoot2.0Java8.

我遵循了一些博客制作教程示例.

教程源代码是:

@GetMapping("/{id}/edit")
public String edit(@PathVariable Long id, Model model) {
  model.addAttribute("categoryDto", categoryService.findOne(id));
  return "category/edit";
}
Run Code Online (Sandbox Code Playgroud)

但是这段代码抛出了这个错误:

categoryService.findOne(ID)

我正在考虑将JPA findOne()方法更改为Optional< S >

怎么解决?

更多信息:

这是categoryService方法:

public Category findOne(Long id) {
  return categoryRepository.findOne(id);
}
Run Code Online (Sandbox Code Playgroud)

dav*_*xxx 115

至少,2.0版本,Spring-Data-Jpa修改findOne().
现在,findOne()没有相同的签名和相同的行为.
以前,它在CrudRepository界面中定义为:

T findOne(ID primaryKey);
Run Code Online (Sandbox Code Playgroud)

现在,findOne()您将找到的单个方法CrudRepository是在QueryByExampleExecutor接口中定义的方法:

<S extends T> Optional<S> findOne(Example<S> example);
Run Code Online (Sandbox Code Playgroud)

最后通过接口SimpleJpaRepository的默认实现来CrudRepository实现.
此方法是通过示例搜索查询,您不希望将其作为替换.

实际上,具有相同行为的方法仍然存在于新API中,但方法名称已更改.
它是从更名findOne()findById()CrudRepository接口:

Optional<T> findById(ID id); 
Run Code Online (Sandbox Code Playgroud)

现在它返回一个Optional.哪个不是很难预防NullPointerException.

所以,现在要调用的实际方法Optional<T> findById(ID id).

怎么用?
学习Optional用法.这里有关于其规格的重要信息:

容器对象,可能包含也可能不包含非null值.如果存在值,则isPresent()将返回true,get()将返回该值.

提供依赖于是否存在包含值的其他方法,例如orElse()(如果值不存在则返回默认值)和ifPresent()(如果值存在则执行代码块).


关于如何使用的一些提示OptionalOptional<T> findById(ID id).

通常,当您按ID查找实体时,如果未检索到该实体,则要返回该实体或进行特定处理.

这里有三个经典的用例.

1)假设如果找到实体你想要得到它,否则你想得到一个默认值.

你可以写:

Foo foo = repository.findById(id)
                    .orElse(new Foo());
Run Code Online (Sandbox Code Playgroud)

或者null如果它有意义,则获取默认值(与API更改之前的行为相同):

Foo foo = repository.findById(id)
                    .orElse(null);
Run Code Online (Sandbox Code Playgroud)

2)假设如果找到实体你想要返回它,否则你想抛出异常.

你可以写:

return repository.findById(id)
        .orElseThrow(() -> new EntityNotFoundException(id));
Run Code Online (Sandbox Code Playgroud)

3)假设您希望根据是否找到实体来应用不同的处理(无需抛出异常).

你可以写:

Optional<Foo> fooOptional = fooRepository.findById(id);
if (fooOptional.isPresent()){
    Foo foo = fooOptional.get();
   // processing with foo ...
}
else{
   // alternative processing....
}
Run Code Online (Sandbox Code Playgroud)

  • 第一部分是错误的:该方法尚未移至`QueryByExampleExecutor`,它只是被重命名为`findById(...)`返回`Optional`.另外,``.map(...)`总是``Optional`,永远不要调用`get()`. (3认同)
  • 也许 EntityNotFoundException 而不是 NotFoundEntity 更好。 (2认同)

Cla*_*uja 6

事实上,在最新版本的 Spring Data 中,findOne 返回一个可选值。如果你想从Optional中检索对象,你可以简单地在Optional上使用get()。首先,存储库应该将可选值返回给服务,然后服务处理可选值为空的情况。之后,服务应该将对象返回给控制器。

  • 建议在“Optional”上调用“....get()”是个坏建议。`Optional` 有专门的方法来处理该值。 (2认同)
  • 事实上,为了处理该值,有更好的方法,例如 .orElse() 或 .orElseThrow()。但是,为了简单地检索项目而不检查存储库调用是否返回所需的对象,.get() 应该这样做 (2认同)

Oli*_*ohm 6

该方法已重命名为findById(…)返回,Optional因此您必须自己处理缺席情况:

Optional<Foo> result = repository.findById(…);

result.ifPresent(it -> …); // do something with the value if present
result.map(it -> …); // map the value if present
Foo foo = result.orElse(null); // if you want to continue just like before
Run Code Online (Sandbox Code Playgroud)

  • 如何考虑返回repository.findById(id).orElseThrow(()-&gt; new NotFoundEntity(id)); (3认同)