Ich arbeite an einem seltsamen Problem. Ich habe Integrationstests durchgeführt und meinen Controller aufgerufen, um ein Objekt aus der Datenbank abzurufen, das nicht vorhanden ist.
public Optional<T> get(Long id) {
try {
return Optional.ofNullable(repository.getOne(id));
} catch(EntityNotFoundException e) {
return Optional.empty();
}
}
Wenn getOne(…)
nichts finden kann, habe ich eine EntityNotFoundException
erwartet, aber eigentlich nichts. Wenn ich mein Ergebnis inspiziere, kann ich sehen, dass ich eine leere Entität mit einem Handler-Link dazu habe "warf EntityNotFoundException
", aber wir gehen nicht in den Haken und ich gebe eine Option dieser seltsamen Entität zurück.
Ich kann dieses Verhalten nicht verstehen.
Dies liegt an der Art und Weise, wie JPA EntityManager.getReference(…)
spezifiziert. Es soll einen Proxy zurückgeben, der entweder das Objekt auflöst, das beim ersten Zugriff auf eine Eigenschaft zurückgegeben wird, oder die enthaltene Ausnahme schließlich auslöst.
Die einfachste Möglichkeit, dies zu umgehen, besteht darin, stattdessen einfach findOne(…)
zu verwenden, wie hier Optional.ofNullable(repository.findOne(…))
. findOne(…)
gibt null
zurück, falls kein Ergebnis gefunden wird.
Eine fortgeschrittenere Methode zur Lösung dieses Problems besteht darin, das Repository Optional
-Instanzen direkt zurückgeben zu lassen. Dies kann erreicht werden, indem eine benutzerdefinierte Basis-Repository-Schnittstelle mit Optional<T>
als Rückgabetyp für die find…
- Methoden erstellt wird.
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> { … }
Ein vollständiges Beispiel finden Sie im Repository für Spring Data-Beispiele .
So hat es für mich funktioniert
public User findUserById(Long id) {
return userRepository.findById(id).orElse(null);
}