web-dev-qa-db-ja.com

Spring DataリポジトリのgetOne(…)がEntityNotFoundExceptionをスローしないのはなぜですか?

私は奇妙な問題に取り組んでいます。統合テストを行っていて、存在しないデータベースからオブジェクトを取得するためにコントローラーを呼び出しています。

_public Optional<T> get(Long id) {

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

getOne(…)が何も見つけられないとき、私はEntityNotFoundExceptionを期待していましたが、実際には何もありませんでした。結果を調べると、「EntityNotFoundException」というハンドラーリンクのある空のエンティティがあることがわかりますが、キャッチに行かず、この奇妙なエンティティのオプションを返します。

この動作を理解できません。

21
Seb

これは、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 Data examples repository でこれの完全な例を見つけてください。

30
Oliver Drotbohm

Spring _@Repository_クラスでは、getOne(id)メソッドは、オブジェクトが照会されるまで(entity.getId()または何かを呼び出すことによって)存在を常に確認するわけではないので、そのようなエンティティの例外ではありません遅れる場合があります。すぐに検証するには、代わりにfindById(id)を使用します(このIDを持つエンティティが存在しない場合は空になる_Optional<EntityType>_を返します)。


これは私のために働いた方法です

_public User findUserById(Long id) {
    return userRepository.findById(id).orElse(null);
}
_
3
VK321