第21章 Infinispan Query DSL
21.1. Infinispan Query DSL リンクのコピーリンクがクリップボードにコピーされました!
Infinispan Query DSL はキャッシュをクエリーするための統一された方法を提供します。これは、ライブラリーモードでインデックス化されたクエリーとインデックスのないクエリーの両方に使用でき、リモートクエリー (Hot Rod Java クライアントを経由) にも使用できます。Infinispan Query DSL では、Lucene ネイティブクエリー API や Hibernate Search クエリー API に依存せずにクエリーを実行できます。
Infinispan Query DSL では、インデックスのないクエリーは JBoss Data Grid リモートおよび埋め込みモードでのみ利用できます。インデックスのないクエリーには設定されたインデックス (「Infinispan Query DSL ベースのクエリー」を参照) は必要ありません。Hibenrate Search や Lucene ベースの API はインデックスのないクエリーを使用できません。
21.2. Infinispan Query DSL を用いたクエリーの作成 リンクのコピーリンクがクリップボードにコピーされました!
新しいクエリー API は org.infinispan.query.dsl パッケージにあります。クエリーは、Search.getQueryFactory()
を使用して取得される QueryFactory
インスタンスを利用して作成されます。各 QueryFactory
インスタンスは 1 つのキャッシュインスタンスにバインドされ、複数の並列クエリーを作成する場合に使用できるステートレスでスレッドセーフなオブジェクトです。
Infinispan Query DSL は以下の手順にしたがってクエリーを実行します。
-
クエリーは
from(Class entityType)
メソッドを呼び出して作成されます。これは、特定のキャッシュから指定のエンティティークラスのクエリーを作成するQueryBuilder
オブジェクトを返します。 -
QueryBuilder
は、DSL メソッドを呼び出して指定される検索基準と設定を累積します。また、構築を完了するQueryBuilder.build()
メソッドを呼び出してQuery
オブジェクトを構築するために使用されます。QueryBuilder
オブジェクトを使用して、入れ子のクエリー以外の複数のクエリーを同時に構築することはできませんが、後で再使用することができます。 -
Query
オブジェクトのlist()
メソッドを呼び出してクエリーを実行し、結果を取得します。実行するとQuery
オブジェクトは再使用できなくなります。新しい結果を取得する必要がある場合は、QueryBuilder.build()
を呼び出して新しいインスタンスを取得します。
クエリーは単一のエンティティー型を対象とし、単一キャッシュの内容全体で評価されます。複数キャッシュでのクエリーの実行や、複数のエンティティー型を対象とするクエリーの作成はサポートされません。
21.3. Infinispan Query DSL ベースのクエリーの有効化 リンクのコピーリンクがクリップボードにコピーされました!
ライブラリーモードでは、Infinispan Query DSL ベースのクエリーの実行は Lucene ベースの API クエリーの実行とほぼ同じです。前提条件は次のとおりです。
- Infinispan Query に必要なすべてのライブラリーがクラスパスにある。詳細は 『Administration and Configuration Guide』を参照してください。
- インデックス化が有効で、キャッシュに対して設定されている (任意)。詳細は、『Administration and Configuration Guide』を参照してください。
- アノテーションが付いた POJO キャッシュ値 (任意)。インデックス化が有効になっていない場合は POJO アノテーションは必要なく、設定されている場合は無視されます。インデックス化が有効になっていない場合、Hibernate Search のアノテーションが付いたフィールドのみではなく、JavaBeans の慣例にしたがうフィールドすべてが検索可能になります。
21.4. Infinispan Query DSL ベースのクエリーの実行 リンクのコピーリンクがクリップボードにコピーされました!
Infinispan Query DSL ベースのクエリーが有効になったら、DSL ベースのクエリーを実行するために Search
から QueryFactory
を取得します。
キャッシュの QueryFactory の取得
ライブラリーモードで、以下のように QueryFactory
を取得します。
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache)
QueryFactory qf = org.infinispan.query.Search.getQueryFactory(cache)
DSL ベースのクエリーの構築
リモートクエリーをリモートクライアントサーバーモードで使用する場合、Search
は org.infinispan.client.hotrod
パッケージにあります。詳細は 「Hot Rod Java クライアント経由のリモートクエリーの実行」の例を参照してください。
複数の条件 (サブ条件を含む) をブール値演算子と組み合わせることも可能です。
複数条件の組み合わせ
このクエリー API は、ユーザーに Lucene クエリーオブジェクト構築の詳細内容を公開しないことで、クエリーの作成方法を簡素化します。また、リモート Hot Rod クライアントが利用できる利点もあります。
以下の例は、Book
エンティティーのクエリーの書き方を示しています。
Book
エンティティーのクエリー
21.5. 射影クエリー リンクのコピーリンクがクリップボードにコピーされました!
多くの場合で、完全なドメインオブジェクトを返す必要はなく、アプリケーションには属性の小さなサブセットのみが必要になります。射影クエリーでは、属性 (または属性のパス) の特定のサブセットを返すことができます。射影クエリーが使用されると、Query.list()
はドメインエンティティー全体 (List<Object>
) を返さずに、アレイの各エントリーが射影された属性に対応する List<Object[]>
を返します。
射影クエリーを定義するには、以下の例のようにクエリーの構築時に select(…)
メソッドを使用します。
書名と発行年の取得
21.6. グループ化および集約操作 リンクのコピーリンクがクリップボードにコピーされました!
Infinispan Query DSL には、グループ化フィールドのセットを基にしてクエリー結果をグループ化する機能や、値のセットに集約関数を適用して各グループからの結果の集約を構築する機能があります。グループ化と集約は、射影クエリーとのみ使用できます。
グループ化フィールドのセットは、groupBy(field)
メソッドを複数回呼び出して指定されます。グループ化フィールドの順番は関係ありません。
射影で選択されたすべての非グループ化フィールドは、以下に説明するグループ化関数の 1 つを使用して集約する必要があります。
著者による本のグループ化とその冊数
集約操作
以下の集約操作を指定のフィールドで実行できます。
-
avg()
-Number
のセットの平均を算出し、Double
として表します。null 以外の値がない場合、結果は null になります。 -
count()
- null でない行の数をLong
として返します。null 以外の値がない場合、結果は 0 になります。 max()
- 指定のフィールドで見つかった最も大きな値と、適用されたフィールドと同じ戻り値の型を返します。null 以外の値がない場合は、結果は null になります。注記指定のフィールドの値は、
Comparable
型である必要があります。そうでないとIllegalStateException
が発生します。min()
- 指定のフィールドで見つかった最も小さな値と、適用されたフィールドと同じ戻り値の型を返します。null 以外の値がない場合は、結果は null になります。注記指定のフィールドの値は、
Comparable
型である必要があります。そうでないとIllegalStateException
が発生します。sum()
-Number
のセットの合計を算出し、返します。戻り値の型は指定のフィールド型によります。null で以外の値がない場合、結果は null になります。以下の表は、指定のフィールドを基にした戻り値の型を表しています。
Expand 表21.1 戻り値の型の合計 フィールド型 戻り値の型 Integral (
BigInteger
以外)Long
Floating Point
Double
BigInteger
BigInteger
BigDecimal
BigDecimal
射影クエリーの特別なケース
射影クエリーでは、以下のケースは特別なユースケースとなります。
- 選択されたフィールドがすべて集約され、グループ化に何も使用されないことが適切である射影クエリー。この場合、集約はグループごとに算出されず、グローバルに算出されます。
- フィールドのグループ化を集約で使用できる。これは、集約が単一のデータポイント上で算出され、値が現在のグループに属する退化したケースになります。
- グループ化フィールドのみを選択し、集約フィールドは選択しないことが適切であるクエリー。
グループ化および集約クエリーの評価
通常のクエリーのように、集約クエリーにフィルター条件を含めることができます。これは、任意でグループ化操作の前後に実行できます。
groupBy
メソッドの呼び出し前に指定されたすべてのフィルター条件は、グループ化操作の実行前に直接キャッシュエントリーに適用されます。これらのフィルター条件は、クエリーされたエンティティー型のプロパティーを参照することがあり、後でグループ化に使用されるデータセットを制限するためのものです。
groupBy
メソッドの呼び出し後に指定されたすべてのフィルター条件は、グループ化操作によって生じる射影に適用されます。これらのフィルター条件は、 groupBy
によって指定されたフィールドまたは集約フィールドを参照できます。select
句に指定されていない集約フィールドの参照は許可されますが、非集約フィールドや非グループ化フィールドの参照は禁止されます。このフェーズをフィルターすると、プロパティーを基にしてグループの数が削減されます。
順序付けも通常のクエリーと同様に指定できます。順序付け操作はグループ化操作の後に実行され、前述のとおりグループ化後のフィルターによって許可されるフィールドを参照できます。
21.7. 名前付きパラメーターの使用 リンクのコピーリンクがクリップボードにコピーされました!
各リクエストに新しいクエリーを作成する代わりに、各実行で置き換えられるパラメーターを含むことが可能です。これにより、クエリーを 1 度に定義でき、必要時にクエリーの変数を調整できます。
having(…)
の比較演算子の右側に Expression.param(…)
演算子を使用すると、クエリーの作成時パラメーターが定義されます。
名前付きパラメーターの定義
名前付きパラメーターの値設定
デフォルトでは、宣言されたパラメーターはすべて null となり、クエリーの実行前に定義されたすべてのパラメーターを null でない値に更新する必要があります。パラメーターの宣言後、クエリーで新しい値を指定して setParameter(parameterName, value)
または setParameters(parameterMap)
を呼び出すと値を更新することができます。また、クエリーを再構築する必要はありません。新しいパラメーターが定義された後に再度実行することができます。
パラメーターを個別に更新
パラメーターのマップとして更新