Je travaillais sur un problème étrange, je faisais des tests d'intégration, appelant mon contrôleur pour obtenir un objet de la base de données qui n'existe pas.
public Optional<T> get(Long id) {
try {
return Optional.ofNullable(repository.getOne(id));
} catch(EntityNotFoundException e) {
return Optional.empty();
}
}
Lorsque getOne(…)
n'est pas en mesure de trouver quoi que ce soit, je m'attendais à un EntityNotFoundException
mais en réalité rien. Si j'inspecte mon résultat, je constate que j'ai une entité vide avec un lien de gestionnaire qui lui est associé "jeté EntityNotFoundException
" mais nous n'allons pas dans la capture et je retourne une option de cette entité étrange.
Je ne peux pas comprendre ce comportement.
Cela est dû à la façon dont JPA a spécifié que EntityManager.getReference(…)
fonctionnait. Il est censé renvoyer un proxy qui résoudra l'objet à renvoyer lors du premier accès à une propriété ou rejettera éventuellement l'exception contenue.
Le moyen le plus simple de contourner ce problème consiste à utiliser simplement findOne(…)
, comme ceci Optional.ofNullable(repository.findOne(…))
. findOne(…)
retournera null
dans le cas où aucun résultat n'est trouvé.
Une façon plus avancée de résoudre ce problème consiste à faire en sorte que le référentiel renvoie directement les instances Optional
. Cela peut être réalisé en créant une interface de référentiel de base personnalisée utilisant Optional<T>
comme type de retour pour les méthodes find…
-.
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> { … }
Vous en trouverez un exemple complet dans le référentiel d'exemples Spring Data .
Voici comment cela a fonctionné pour moi
public User findUserById(Long id) {
return userRepository.findById(id).orElse(null);
}