SpringBoot2.0
でJava8
を学習しています。
そして、いくつかのブログ作成チュートリアルの例に従いました。
チュートリアルのソースコードは次のとおりです。
@GetMapping("/{id}/edit")
public String edit(@PathVariable Long id, Model model) {
model.addAttribute("categoryDto", categoryService.findOne(id));
return "category/edit";
}
しかし、このコードはこのエラーを投げています:
categoryService.findOne(id)
JPA findOne()
メソッドをOptional< S >
に変更することを考えています
それを解決する方法は?
詳細:
これはcategoryServiceメソッドです。
public Category findOne(Long id) {
return categoryRepository.findOne(id);
}
少なくとも、2.0
バージョン、Spring-Data-Jpa
はfindOne()
を変更しました。
現在、findOne()
には同じシグネチャと同じ動作がありません。
以前は、CrudRepository
インターフェイスで次のように定義されていました。
T findOne(ID primaryKey);
ここで、CrudRepository
にある単一のfindOne()
メソッドは、QueryByExampleExecutor
インターフェースで次のように定義されています。
<S extends T> Optional<S> findOne(Example<S> example);
これは、最後にSimpleJpaRepository
インターフェイスのデフォルト実装であるCrudRepository
によって実装されます。
このメソッドはサンプル検索によるクエリであり、置換として使用することは望ましくありません。
実際、同じAPIのメソッドは新しいAPIにまだありますが、メソッド名は変更されています。CrudRepository
インターフェイスでfindOne()
からfindById()
に名前が変更されました。
Optional<T> findById(ID id);
現在、Optional
を返します。 NullPointerException
を防ぐのはそれほど悪くありません。
つまり、実際に呼び出すメソッドはOptional<T> findById(ID id)
です。
使い方は?
学習 Optional
使用法。ここにその仕様に関する重要な情報:
Null以外の値を含む場合と含まない場合があるコンテナオブジェクト。値が存在する場合、isPresent()はtrueを返し、get()は値を返します。
OrElse()(値が存在しない場合はデフォルト値を返す)やifPresent()(値が存在する場合はコードブロックを実行する)など、含まれる値の有無に依存する追加のメソッドが提供されます。
Optional
をOptional<T> findById(ID id)
とともに使用する方法に関するヒント
通常、IDでエンティティを検索するときに、エンティティを返すか、取得されない場合は特定の処理を行います。
ここでは、古典的な3つの使用例を示します。
1)エンティティが見つかった場合、それを取得したい場合、デフォルト値を取得したいとします。
あなたは書くことができます:
Foo foo = repository.findById(id)
.orElse(new Foo());
または、意味がある場合はnull
のデフォルト値を取得します(APIの変更前と同じ動作):
Foo foo = repository.findById(id)
.orElse(null);
2)エンティティが見つかった場合、それを返したい場合、例外をスローしたいとします。
あなたは書くことができます:
return repository.findById(id)
.orElseThrow(() -> new EntityNotFoundException(id));
3)エンティティが見つかったかどうかに応じて(必要な例外をスローせずに)別の処理を適用するとします。
あなたは書くことができます:
Optional<Foo> fooOptional = fooRepository.findById(id);
if (fooOptional.isPresent()){
Foo foo = fooOptional.get();
// processing with foo ...
}
else{
// alternative processing....
}
メソッドはfindById(…)
に名前が変更され、Optional
を返すため、自分で不在を処理する必要があります。
Optional<Foo> result = repository.findById(…);
result.ifPresent(it -> …); // do something with the value if present
result.map(it -> …); // map the value if present
Foo foo = result.orElse(null); // if you want to continue just like before
Optional
apiは、値を取得するためのメソッドを提供します。 isPresent()
で値の存在を確認してからget()
を呼び出すか、get()
でチェーンされたorElse()
を呼び出してデフォルト値を指定できます。
最後に試すことができるのは、カスタムメソッドで@Query()
を使用することです。
実際、Spring Dataの最新バージョンでは、findOneはオプションを返します。 Optionalからオブジェクトを取得する場合は、Optionalでget()を使用するだけです。ただし、まず最初に、リポジトリはサービスにオプションを返す必要があります。その後、サービスはオプションが空の場合を処理します。その後、サービスはオブジェクトをコントローラーに返す必要があります。
私は常にデフォルトのメソッド"findByIdOrError"を広く使用されているCrudRepositoryリポジトリ/インターフェースで記述します。
@Repository
public interface RequestRepository extends CrudRepository<Request, Integer> {
default Request findByIdOrError(Integer id) {
return findById(id).orElseThrow(EntityNotFoundException::new);
}
}