Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does getOne(…) on a Spring Data repository not throw an EntityNotFoundException?

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.

like image 498
Seb Avatar asked Aug 28 '15 06:08

Seb


People also ask

Are Spring repositories thread safe?

It is not thread safe by default, thus it needs to be managed (read: correctly bound to a thread and proxied to point to the thread-bound instance).

How does Spring data repository Work?

These Repositories are Java interfaces that allow you as the developer to define a data access contract. The Spring Data JPA framework can then inspect that contract, and automatically build the interface implementation under the covers for you.

Should I use JpaRepository or CrudRepository?

Crud Repository doesn't provide methods for implementing pagination and sorting. JpaRepository ties your repositories to the JPA persistence technology so it should be avoided. We should use CrudRepository or PagingAndSortingRepository depending on whether you need sorting and paging or not.


1 Answers

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 nullin 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.

like image 111
Oliver Drotbohm Avatar answered Oct 06 '22 07:10

Oliver Drotbohm