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.
I can't understand this behavior.
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.
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.
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.
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.
This is how it worked for me
public User findUserById(Long id) {
return userRepository.findById(id).orElse(null);
}