简体   繁体   English

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

[英]Spring Data JPA findOne() change to Optional how to use this?

I'm learning SpringBoot2.0 with Java8 .我正在用Java8学习SpringBoot2.0

And I followed some blog-making tutorial example.我遵循了一些博客制作教程示例。

The tutorial source code is:教程源代码为:

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

But this code is throwing this error:但是这段代码抛出了这个错误:

categoryService.findOne(id) categoryService.findOne(id)

I'm thinking about changing the JPA findOne() method to Optional< S >我正在考虑将 JPA findOne()方法更改为Optional< S >

How to solve that?如何解决?

More info:更多信息:

This is the categoryService method:这是 categoryService 方法:

public Category findOne(Long id) {
  return categoryRepository.findOne(id);
}

From at least, the 2.0 version, Spring-Data-Jpa modified findOne() .至少从2.0版本开始, Spring-Data-Jpa修改了findOne()
Now, findOne() has neither the same signature nor the same behavior.现在, findOne()既没有相同的签名,也没有相同的行为。
Previously, it was defined in the CrudRepository interface as:以前,它在CrudRepository接口中定义为:

T findOne(ID primaryKey);

Now, the single findOne() method that you will find in CrudRepository is the one defined in the QueryByExampleExecutor interface as:现在,您将在CrudRepository找到的单个findOne()方法是在QueryByExampleExecutor接口中定义的QueryByExampleExecutor

<S extends T> Optional<S> findOne(Example<S> example);

That is implemented finally by SimpleJpaRepository , the default implementation of the CrudRepository interface.这最终由SimpleJpaRepository实现,它是CrudRepository接口的默认实现。
This method is a query by example search and you don't want that as a replacement.此方法是按示例搜索查询,您不希望将其作为替代。

In fact, the method with the same behavior is still there in the new API, but the method name has changed.实际上,在新的 API 中,行为相同的方法仍然存在,只是方法名称发生了变化。
It was renamed from findOne() to findById() in the CrudRepository interface :它在CrudRepository接口中从findOne()重命名为findById()

Optional<T> findById(ID id); 

Now it returns an Optional , which is not so bad to prevent NullPointerException .现在它返回一个Optional ,这对于防止NullPointerException来说还不错。

So, the actual method to invoke is now Optional<T> findById(ID id) .因此,调用的实际方法现在是Optional<T> findById(ID id)

How to use that?怎么用那个?
Learning Optional usage.学习Optional用法。 Here's important information about its specification:以下是有关其规格的重要信息:

A container object which may or may not contain a non-null value.可能包含也可能不包含非空值的容器对象。 If a value is present, isPresent() will return true and get() will return the value.如果存在值,isPresent() 将返回 true,get() 将返回该值。

Additional methods that depend on the presence or absence of a contained value are provided, such as orElse() (return a default value if value not present) and ifPresent() (execute a block of code if the value is present).提供了依赖于所包含值的存在与否的其他方法,例如 orElse()(如果值不存在则返回默认值)和 ifPresent()(如果该值存在则执行代码块)。


Some hints on how to use Optional with Optional<T> findById(ID id) .关于如何将OptionalOptional<T> findById(ID id)一起使用的一些提示。

Generally, as you look for an entity by id, you want to return it or make a particular processing if that is not retrieved.通常,当您按 id 查找实体时,您希望返回它或在未检索到的情况下进行特定处理。

Here are three classical usage examples.以下是三个经典用法示例。

  1. Suppose that if the entity is found you want to get it otherwise you want to get a default value.假设如果找到实体,您想要获取它,否则您想要获取默认值。

You could write :你可以写:

Foo foo = repository.findById(id)
                    .orElse(new Foo());

or get a null default value if it makes sense (same behavior as before the API change) :或者在有意义的情况下获取null默认值(与 API 更改之前的行为相同):

Foo foo = repository.findById(id)
                    .orElse(null);
  1. Suppose that if the entity is found you want to return it, else you want to throw an exception.假设如果找到实体你想返回它,否则你想抛出一个异常。

You could write :你可以写:

return repository.findById(id)
        .orElseThrow(() -> new EntityNotFoundException(id));
  1. Suppose you want to apply a different processing according to if the entity is found or not (without necessarily throwing an exception).假设您想根据是否找到实体来应用不同的处理(不必抛出异常)。

You could write :你可以写:

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

The method has been renamed to findById(…) returning an Optional so that you have to handle absence yourself:该方法已重命名为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

I always write a default method "findByIdOrError" in widely used CrudRepository repos/interfaces.我总是在广泛使用的 CrudRepository 存储库/接口中编写一个默认方法“findByIdOrError”

@Repository 
public interface RequestRepository extends CrudRepository<Request, Integer> {

    default Request findByIdOrError(Integer id) {
        return findById(id).orElseThrow(EntityNotFoundException::new);
    } 
}

Indeed, in the latest version of Spring Data, findOne returns an optional.事实上,在最新版本的 Spring Data 中, findOne 返回一个可选的。 If you want to retrieve the object from the Optional, you can simply use get() on the Optional.如果要从 Optional 中检索对象,只需在 Optional 上使用 get() 即可。 First of all though, a repository should return the optional to a service, which then handles the case in which the optional is empty.但是,首先,存储库应该将可选项返回给服务,然后服务处理可选项为空的情况。 afterwards, the service should return the object to the controller.之后,服务应该将对象返回给控制器。

Optional api provides methods for getting the values. Optional api 提供了获取值的方法。 You can check isPresent() for the presence of the value and then make a call to get() or you can make a call to get() chained with orElse() and provide a default value.您可以检查isPresent()的价值的存在,然后拨打电话,以get()或者你可以拨打电话,以get()与链orElse()并提供一个默认值。

The last thing you can try doing is using @Query() over a custom method.您可以尝试做的最后一件事是在自定义方法上使用@Query()

Consider an User entity and UserRepository .考虑一个User实体和UserRepository In service package code like below.在如下服务包代码中。

Optional<User> resultUser = UserRepository.findById(userId);  //return Optional

User createdUser = resultUser.get();  //return User

Now you can access all the User entity attributes using getter.现在您可以使用 getter 访问所有用户实体属性。

createdUser.getId(); 
createdUser.getName();

like that.像那样。

The findOne method of the CrudRepository interface has been replaced by findById since version 2.0 of Spring Data Commons.自 Spring Data Commons 2.0 版以来,CrudRepository 接口的 findOne 方法已被 findById 取代。 you replace findOne(id) by: findById(id).orElse(null)您将 findOne(id) 替换为: findById(id).orElse(null)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM