doc.dev1x.org

Query Object

1. 目的

検索条件をオブジェクト(Criteria)としてカプセル化し、find() などのメソッドに渡すことで、動的な検索条件の組み立てを柔軟かつ安全に行う

2. 課題

条件が動的に変わる検索処理を素朴に実装しようとすると、以下の問題が起きる。

3. 解決策

検索条件・ページング・ソートを Criteria オブジェクト1つ にまとめ、find(criteria) に渡す。

条件の組み立て・クエリへの変換・実行がそれぞれ分離される。

4. メリット

Repository のインタフェースが安定する

条件が増えても find(criteria) のシグネチャを変えなくてよい

動的条件の組み立てが自然に書ける

未入力項目のスキップなどを Criteria 内に閉じられる

ページング・ソートを一元管理できる

引数が増えない

権限による絞り込みをレイヤーで分離できる

Criteria に追加するだけで制御できる

テストがしやすい

Criteria を差し替えるだけでさまざまなケースを検証できる

URL パラメータとの親和性が高い

POJO なのでシリアライズ・デシリアライズが容易

5. デメリット

シンプルな検索には過剰

条件が固定・少ない場合はクエリメソッドの方が明快

Criteria が肥大化しやすい

機能追加を重ねると何でも入ったオブジェクトになりがち

学習コストがある

Specification や CriteriaBuilder などフレームワーク固有の API の理解が必要

複雑な JOIN には限界がある

多テーブルにまたがる集計などはネイティブクエリや QueryDSL との併用が必要になる

6. 注意事項

適用範囲を絞る

管理ツール・検索特化画面など動的条件が多い場所に限定し、一般ユーザー向けの固定画面には使わない

Criteria の肥大化を防ぐ

機能ごとに Criteria を分割し、1クラスに詰め込みすぎない

ユーザーが自由にクエリを組み立てるのとは別物

検索項目は設計者が固定し、条件の与え方をユーザーに委ねるに留める

パフォーマンスを意識する

動的条件でもインデックスが効くかどうかを意識して設計する

段階的に導入する

最初からCriteriaを設計するのではなく、クエリメソッドが限界を迎えてから移行するのが健全

参考資料