Подтвердить что ты не робот

Почему getOne (...) в хранилище данных Spring не выбрасывает EntityNotFoundException?

Я работаю над странной проблемой, я делаю интеграционное тестирование, вызывая мой контроллер, чтобы получить объект из базы данных, которая не существует.

public Optional<T> get(Long id) {

  try {
    return Optional.ofNullable(repository.getOne(id));
  } catch(EntityNotFoundException e) {
    return Optional.empty();
  }
}

Когда getOne(…) ничего не может найти, я ожидал EntityNotFoundException, но на самом деле ничего. Если я проверю свой результат, я вижу, что у меня есть пустой объект с ссылкой обработчика "threw EntityNotFoundException", но мы не ходим в catch и возвращаем необязательный этот странный объект.

Я не понимаю этого поведения.

4b9b3361

Ответ 1

Это связано с тем, как JPA указывает EntityManager.getReference(…) на работу. Он должен возвращать прокси-сервер, который будет либо разрешать объект, который будет возвращен при первом доступе свойства, либо в конечном итоге выбросить содержащееся исключение.

Самый простой способ обойти это - просто использовать findOne(…) вместо этого, как этот Optional.ofNullable(repository.findOne(…)). findOne(…) вернет null, если результат не найден.

Более продвинутый способ разрешить это - сделать репозиторий напрямую возвратом экземпляров Optional. Этого можно достичь, создав интерфейс пользовательского базового репозитория, используя Optional<T> в качестве типа возврата для методов 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> { … }

Найдите полный пример этого в Spring репозитории примеров данных.

Ответ 2

В классах Spring @Repository метод getOne(id) не всегда проверяет существование до тех пор, пока объект не будет запрошен (вызывая entity.getId() или что-то еще), поэтому исключение no-such-entity может быть отложено. Чтобы проверить сразу, используйте findById(id) вместо этого (который возвращает Optional<EntityType> который будет пустым, если сущность с таким идентификатором не существует).


Вот как это работает для меня

public User findUserById(Long id) {
    return userRepository.findById(id).orElse(null);
}