I'm learning SpringBoot2.0
with Java8
.
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)
I'm thinking about changing the JPA findOne()
method to Optional< S >
How to solve that?
More info:
This is the categoryService method:
public Category findOne(Long id) { return categoryRepository.findOne(id); }
Optional<T> is a container object which may or may not contain a non-null value. If a value is present, isPresent returns true and get returns the value. The ifPresent invokes the specified method if the value is present; otherwise nothing is done.
The calling findById() returns an eagerly fetched entity whereas Calling getOne() returns a lazily fetched entity.
As a consequence, findById() returns the actual object and getById returns a reference of the entity.
Optional is a container object which may or may not contain a non-null value. You must import java. util package to use this class. If a value is present, isPresent() will return true and get() will return the value.
From at least, the 2.0
version, Spring-Data-Jpa
modified findOne()
.
Now, findOne()
has neither the same signature nor the same behavior.
Previously, it was defined in the CrudRepository
interface as:
T findOne(ID primaryKey);
Now, the single findOne()
method that you will find in CrudRepository
is the one defined in the QueryByExampleExecutor
interface as:
<S extends T> Optional<S> findOne(Example<S> example);
That is implemented finally by SimpleJpaRepository
, the default implementation of the CrudRepository
interface.
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.
It was renamed from findOne()
to findById()
in the CrudRepository
interface :
Optional<T> findById(ID id);
Now it returns an Optional
, which is not so bad to prevent NullPointerException
.
So, the actual method to invoke is now Optional<T> findById(ID id)
.
How to use that?
Learning Optional
usage. 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.
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).
Some hints on how to use Optional
with Optional<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.
Here are three classical usage examples.
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) :
Foo foo = repository.findById(id) .orElse(null);
You could write :
return repository.findById(id) .orElseThrow(() -> new EntityNotFoundException(id));
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:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With