照会キューを使用して、アプリケーションはエンティティーに対し、照会によって限定されるキューを サーバー・サイドまたはローカルの eXtreme Scale に 作成できます。照会結果のエンティティーは、このキューに 保管されます。現在、照会キューは、ペシミスティック・ロック・ストラテジーを使用している マップでのみサポートされます。
照会キューは複数のトランザクションおよびクライアントによって共有されます。 照会キューが空になると、このキューに関連付けられたエンティティー照会が再実行され、新しい結果がキューに追加されます。照会キューは、エンティティー照会ストリングとパラメーターによって 一意的に識別されます。 1 つの ObjectGrid インスタンス内に存在する各固有の照会キューのインスタンスは 1 つのみです。追加情報については、EntityManager API 資料を 参照してください。
次の例は、照会キューの 使用法を示します。
/**
* Get a unassigned question type task
*/
private void getUnassignedQuestionTask() throws Exception {
EntityManager em = og.getSession().getEntityManager();
EntityTransaction tran = em.getTransaction();
QueryQueue queue = em.createQueryQueue("SELECT t FROM Task t
WHERE t.type=?1 AND t.status=?2", Task.class);
queue.setParameter(1, new Integer(Task.TYPE_QUESTION));
queue.setParameter(2, new Integer(Task.STATUS_UNASSIGNED));
tran.begin();
Task nextTask = (Task) queue.getNextEntity(10000);
System.out.println("next task is " + nextTask);
if (nextTask != null) {
assignTask(em, nextTask);
}
tran.commit();
}
上記の例は、最初にエンティティー照会ストリング "SELECT t FROM Task t WHERE t.type=?1 AND t.status=?2" を使用して QueryQueue を作成しています。その次に、QueryQueue オブジェクトのパラメーターを設定しています。 この照会キューは、タイプが "question" のすべての "unassigned" (未割り当て) タスクを示します。 QueryQueue オブジェクトは、エンティティー Query オブジェクトに非常によく似ています。
QueryQueue が 作成されると、エンティティー・トランザクションが開始され、getNextEntity メソッドが呼び出されます。 このメソッドは、タイムアウト値が 10 秒に設定され、次に使用可能なエンティティーを 取得します。エンティティーが取得されると、それは assignTask メソッドで処理されます。assignTask は Task エンティティー・インスタンスを変更し、 状況を "assigned" (割り当て済み) に変更します。これにより、このエンティティーは もはや QueryQueue のフィルターに一致しなくなるため、 事実上キューから削除されます。割り当てが終わると、トランザクションがコミットされます。
エンティティーをループで 取得できます。以下に、未割り当て (UNASSIGNED) の質問 (QUESTION) タイプのすべてのタスクを 完了させる方法の例を示します。
/**
* Get all unassigned question type tasks
*/
private void getAllUnassignedQuestionTask() throws Exception {
EntityManager em = og.getSession().getEntityManager();
EntityTransaction tran = em.getTransaction();
QueryQueue queue = em.createQueryQueue("SELECT t FROM Task t WHERE
t.type=?1 AND t.status=?2", Task.class);
queue.setParameter(1, new Integer(Task.TYPE_QUESTION));
queue.setParameter(2, new Integer(Task.STATUS_UNASSIGNED));
Task nextTask = null;
do {
tran.begin();
nextTask = (Task) queue.getNextEntity(10000);
if (nextTask != null) {
System.out.println("next task is " + nextTask);
}
tran.commit();
} while (nextTask != null);
}
エンティティー・マップ内に未割り当ての質問タイプの タスクが 10 個あった場合、ユーザーは、10 個のエンティティーがコンソールに プリントされると予想したでしょう。しかし、このサンプルを実行すると、 予想に反して、プログラムは永久に終了しません。
照会キューが 作成され、getNextEntity が呼び出されると、キューに関連付けられたエンティティー照会が実行され、 キューには 10 件の結果が追加されます。getNextEntity が呼び出されると、1 つのエンティティーが キューから取り出されます。getNextEntity 呼び出しが 10 回実行されると、 キューは空になります。エンティティー照会が自動的に再実行されます。これら 10 個のエンティティーはまだ存在し、照会キューのフィルター条件に一致するため、 それらは再度キューに追加されます。
次の行を println() ステートメントの 後に追加すれば、10 個のエンティティーのみが プリントされるようになります。
em.remove(nextTask);
コンテナーごとの配置デプロイメントでの SessionHandle と QueryQueue の使用について詳しくは、SessionHandle 統合を参照してください。
分散 eXtreme Scale では、 照会キューを 1 つの区画またはすべての区画に作成できます。 照会キューをすべての区画に作成する場合、各区画に 1 つの 照会キュー・インスタンスが存在します。
クライアントは、QueryQueue.getNextEntity または QueryQueue.getNextEntities メソッドを使用して次のエンティティーを取得しようとするとき、 要求を区画の 1 つに送信します。クライアントは、照合要求とピン要求を サーバーに送信します。
すべての区画 (n 個) にデプロイされる照会キューのエンティティーを 取得する方法の例を以下に示します。
エンティティー・マネージャーに QueryQueue オブジェクトを作成するメソッドは、次のとおりです。
public QueryQueue createQueryQueue(String qlString, Class entityClass);
照会キュー 内の結果は、メソッドの 2 番目のパラメーターで定義されたオブジェクト である Class entityClass に射影されます。
このパラメーターが指定された場合、 クラスには、照会ストリングで指定されたものと同じエンティティー名が 必要です。これは、エンティティーをサブセット・エンティティーに 射影する場合に便利です。エンティティー・クラスにヌル値が使用された場合は、 結果には何も射影されません。マップに保管される値は、 エンティティー・タプル・フォーマットになります。
分散 eXtreme Scale 環境の場合、 ペシミスティック・ロック・モードを使用する eXtreme Scale マップでのみ 照会キューがサポートされます。したがって、クライアント・サイドにニア・キャッシュは存在しません。 しかし、クライアントはトランザクション・マップ内にデータ (キーと値) を 保持している可能性があります。このため、サーバーから取得されたエンティティーが、 既にトランザクション・マップ内にあるエントリーと同じキーを 共有していた場合、キー競合につながる可能性があります。
キー競合は、トランザクション・マップ内にデータが 存在する場合のみ発生します。すなわち、それが発生するのは、 既にダーティーな (新規データが挿入されたか、データが更新された) トランザクション内で getNextEntity または getNextEntities 呼び出しが呼び出されたときに限られます。 アプリケーションでキー競合を発生させないようにするには、常に ダーティーでないトランザクション内で getNextEntity または getNextEntities を 呼び出す必要があります。
最初のケースでは、サーバーは応答をクライアントに 送信しようとするときに、クライアントのダウンをディスカバーします。 2 番目のケースでは、クライアントが 1 つ以上のエンティティーをサーバーから取得すると、 それらのエンティティーに X ロックがかけられます。クライアントがダウンすると、 トランザクションは最終的にタイムアウトになり、X ロックは解放されます。
通常、照会キューでは ORDER BY 文節が 守られません。照会キューから getNextEntity または getNextEntities を 呼び出すと、エンティティーが順序どおりに返される 保証はありません。その理由は、区画間でエンティティーを 正しい順序にすることができないためです。照会キューがすべての区画にデプロイされる ケースでは、getNextEntity または getNextEntities 呼び出しが実行されると、 要求を処理する区画がランダムに選出されます。このため、 順序は保証されません。
照会キューが単一区画にデプロイされる場合は、ORDER BY が守られます。
詳しくは、 EntityManager 照会 APIを参照してください。
各 QueryQueue.getNextEntity 呼び出しまたは QueryQueue.getNextEntities 呼び出しは、1 つのランダム区画から一致したエンティティーを取得します。 アプリケーションは 1 つのトランザクションで QueryQueue.getNextEntity または QueryQueue.getNextEntities を 1 回だけ呼び出さなければなりません。 そうでなければ、eXtreme Scale は複数の区画からエンティティーをタッチすることになり、コミット時に例外がスローされます。