TopLinkを使用すると、リレーショナルや非リレーショナルのデータ・ソースに対して、Java EEおよびJava EE以外のアプリケーションの両方で問合せを使用して、永続オブジェクトまたはデータを作成、読取り、更新および削除できます。
この章の内容は次のとおりです。
表108-1は、TopLinkで作成できる問合せのタイプを示します。
表108-1 TopLink問合せのタイプ
問合せのタイプ | 説明 | Oracle JDeveloper |
TopLink Workbench | Java |
---|---|---|---|---|
|
この問合せは、オブジェクトに対する最も一般的なデータ・ソース・アクションの実行に使用される入力パラメータに基づいて、 |
|
|
|
|
この問合せは、問合せオブジェクトの問合せとも呼ばれます。オブジェクトまたはデータのいずれかに対するデータ・ソース・アクションを実行するために作成し実行する、 |
|
|
|
|
|
|||
|
開発者が作成する |
|||
|
名前付き問合せで設定された |
|
|
|
|
TopLink |
|
|
|
|
インタフェースのタイプまたは継承階層のスーパー・クラスおよびサブクラスを参照する問合せです。 |
|
|
|
|
|
|||
|
Enterprise Beanを戻すEnterprise Beanのホーム・インタフェースで定義される問合せです。 |
詳細は、次を参照してください。
一般的に、データ・ソースの問合せとは、データ・ソースの内容に対する操作の実行、データ・ソースの内容との相互作用を意味します。データ・ソースの問合せを行うには、次のことができる必要があります。
問い合せるデータ・ソースのネイティブな構文で操作を定義します。
制御された方法で操作を適用します。
操作によって結果が返された場合は、それを管理します。
また、TopLinkでは、問合せがTopLinkキャッシュにどのような影響を与えるのかも考慮する必要があります。詳細は、108.16項「問合せとキャッシュ」を参照してください。
この項では、次の内容を含む、TopLinkに固有の問合せの概念について説明します。
TopLinkでは、Call
オブジェクトがデータ・ソースへの操作をカプセル化します。TopLinkには、Structured Query Language(SQL)、Enterprise Java Bean Query Language(EJB QL)、Java Persistence Query Language(JP QL)、eXtensible Markup Language(XML)、および企業情報システム(EIS)など、様々なタイプのCall
があります。
Call
は、直接実行することも、あるいはDatabaseQuery
のコンテキストで実行することもできます。
DatabaseQuery
オブジェクトは、追加のカスタマイズ・オプションや最適化オプションとCall
でカプセル化した操作を関連付ける抽象オブジェクトです。TopLinkでは、これらのオプションをCall
から分離することによって、すべてのCall
タイプにわたって高度な問合せ機能を利用できます。
詳細は、108.7項「データベース問合せ」を参照してください。
TopLinkでは、問合せをオブジェクトまたはデータに対して次のように定義できます。
オブジェクト・レベルの問合せ(108.7.1項「オブジェクト・レベルの読取り問合せ」および108.7.3項「オブジェクト・レベルの変更問合せ」を参照)は、オブジェクト固有であり、データをドメイン・モデルのオブジェクトとして返します。これは、マップ済データ向きの問合せです。オブジェクト・レベルのDatabaseQuery
問合せは、TopLinkで最も頻繁に使用されます。
データ・レベルの問合せ(108.7.2項「データ・レベルの読取り問合せ」および108.7.4項「データ・レベルの変更問合せ」を参照)は、データベース表を直接問い合せるために使用され、マップされないデータの扱いに適した方法です。
データ・レベルの問合せが行データを返し、オブジェクト・レベルの問合せがドメイン・モデルのオブジェクトを返すのに対し、サマリー問合せはオブジェクトに関するデータを返します。TopLinkでは、部分オブジェクト問合せとレポート問合せを使用できます。部分オブジェクト問合せ(108.7.1.3項「部分オブジェクト問合せ」を参照)では、特定の属性のみを移入したオブジェクトのセットを返します。また、レポート問合せ(108.7.5項「レポート問合せ」を参照)では、オブジェクトのセットの特定の属性を要約またはロールアップしたデータを返します。
特定のクラスに適用できる名前付き問合せを保存できるのみでなく(108.8項「名前付き問合せ」を参照)、一般的なデータ・ソース操作用にTopLinkで定義されているデフォルトの操作をDescriptorQueryManager
によってオーバーライドすることもできます。詳細は、108.13項「ディスクリプタ問合せマネージャ問合せ」を参照してください。
TopLinkの式を使用すると、ドメイン・オブジェクト・モデルに基づいて問合せの検索基準を指定できます。問合せを実行する際、TopLinkではこれらの検索基準を、使用しているプラットフォームに適した問合せ言語に変換します。
TopLinkは、式をサポートする次の2種類のパブリック・クラスを提供します。
Expression
クラスは、単純な定数からブール・ロジックを伴う複雑な句まで、あらゆる式を表します。式の操作、グループ化および統合を行うことができます。
ExpressionBuilder
クラスは、新しい式を構成するためのファクトリです。
選択基準は、DatabaseQuery
のメソッドsetSelectionCriteria
(108.7項「データベース問合せ」を参照)を使用してExpression
として指定したり、Expression
を取るファインダ(108.15.7項「式ファインダ」を参照)に指定できます。
TopLinkの式の使用の詳細は、第110章「TopLinkの式の概要」を参照してください。
問合せキーとは、データベース・フィールド名の、スキーマ非依存の別名です。問合せキーを使用する場合、スキーマに依存しない別名を使用したフィールドを参照できます。リレーショナル・プロジェクトにかぎっては、TopLinkではマップした属性すべてに対して問合せキーを自動的に作成します。問合せキーの名前は、オブジェクト・モデルで指定されたクラス属性の名前です。
問合せキーは、クラス・ディスクリプタ(119.10項「問合せキーの構成」を参照)またはインタフェース・ディスクリプタ(119.11項「インタフェース問合せキーの構成」を参照)で構成できます。
式で問合せキーを使用して(110.4項「問合せキーと問合せ式」を参照)、可変1対1マッピングについて問い合せることができます(111.8項「可変1対1マッピングに対する問合せの使用」を参照)。
TopLinkを使用すると、次の問合せ言語のいずれかを使用して問合せを表現できます。
TopLinkの式(第110章「TopLinkの式の概要」を参照)
ほとんどの場合、指定の問合せ言語で直接、問合せを構成できます。または、可能であれば、適切なCall
を使用してDatabaseQuery
を作成し、TopLink Expression
を使用して選択基準を指定します。問合せをSQLで直接構成する方法が最も簡単なアプローチのように見えますが(簡単な操作やマップされていないデータへの操作の場合は事実そのとおりです)、DatabaseQuery
のアプローチを使用した方が、問合せをドメイン・オブジェクト・モデルに限定でき、データ・ソース・スキーマ実装の詳細への依存を避けられるという、大きな利点があります。
問合せの構成には、JP QLまたはExpression
を使用することをお薦めします。
SQLは、リレーショナル・データベース・データ・ソースを使用するアプリケーションで最も一般的な問合せ言語です。
Session
のメソッドexecuteSelectingCall
およびexecuteNonSelectingCall
を使用してカスタムSQLを直接実行したり、適切なCall
を使用してDatabaseQuery
を構成することができます。
TopLinkでは、ストアド・プロシージャ、およびOracleデータベース、ストアド・ファンクションとともに使用できる様々なSQL Call
オブジェクトを用意しています。詳細は、108.9.1項「SQLコール」を参照してください。
TopLinkでは、PL/SQLデータ・タイプを持つOracleストアド・プロシージャのPL/SQLコールもサポートします。詳細は、109.5項「StoredProcedureCallの使用」を参照してください。
EJB QLは、SQLと同様に問合せ言語ですが、SQLとは異なり、オブジェクト・モデルの観点から問合せを表したもので、これを使用すると、ユーザーはオブジェクト・モデル内の各抽象エンティティBeanの属性を使用して問合せを宣言できます。また、EJB QLには、エンティティBeanと依存オブジェクトの間で定義されているリレーションシップのナビゲーションを可能にするパス式が含まれます。
EJB QLには次のような利点があります。
データベース構造(表、フィールドなど)を知っている必要がありません。
データベースの表やフィールドを使用するかわりにエンティティBeanの属性を使用して、問合せを構成できます。
問合せでリレーションシップを使用して、属性間をナビゲーションできます。
EJB QL問合せはデータベースに依存しないため、移植性があります。
SELECT
句に参照クラスを指定できます。
EJB QL問合せの短所は、複雑な問合せを構成する場合に使用方法が難しいことです。
TopLinkでは、EJB QLの仕様が完全にサポートされています。
注意: TopLinkでは、LOCATE 文字列関数がサポートされ、この関数を使用して正しいSQLが生成されます。ただし、一部のデータ・ソースではLOCATE をサポートしていません。LOCATE 文字列関数を使用する前に、データ・ソースのドキュメントを参照してください。 |
EJB QLは、EJB 2.0の仕様で最初に定義された標準的な問合せ言語です。このため、TopLinkでは、EJBファインダでEJB QL(108.15.8項「EJB QLファインダ」を参照)を使用して選択基準を指定できるようにしています。
通常、EJB QLはEJBに関連付けられていますが、TopLinkでは普通のJavaオブジェクトの問合せでEJB QLを使用して選択基準を指定することもできます。TopLinkで提供するEJB QL Call
は、直接実行することも、あるいはDatabaseQuery
のコンテキストで実行することもできます。詳細は、108.9.2項「EJB QLコール」および108.2.2項「DatabaseQuery」を参照してください。
詳細は、『EclipseLink Developer's Guide』の「What You May Need to Know About Querying with Java Persistence Query Language」(http://wiki.eclipse.org/Developing_Applications_Using_EclipseLink_JPA_%28ELUG%29#What_You_May_Need_to_Know_About_Querying_with_Java_Persistence_Query_Language
)を参照してください。
TopLink XMLを使用して、OracleデータベースXMLTypeフィールドに格納されているXMLデータを問い合せることができます。詳細は、27.4項「XMLタイプへ直接マッピング」および110.2.4項「XMLType関数」を参照してください。
EIS Call
(108.9.3項「企業情報システム(EIS)インタラクション」を参照)を使用してTopLink問合せを実行すると、選択基準が、使用しているJCAアダプタに適したXML形式に変換されます。
XQuery言語がJCAアダプタでサポートされている場合、XQuery言語を使用できるようにするには、XQueryインタラクション(108.9.3.4項「XQueryInteraction」を参照)を直接またはDatabaseQuery
のコンテキストで実行します。
例による問合せは、簡単で直感的な問合せ表現方法です。例による問合せを指定するには、問合せの対象となる永続オブジェクトのサンプル・インスタンスを指定し、問い合せるデータ・メンバーにのみ適切な値を設定します。
例による問合せを使用すると、ダイレクト・マッピングまたは1対1リレーションシップ(ネストしているものを含む)を使用する属性を基準にオブジェクトを問い合せることができます。
注意: 例による問合せでは、これ以外のリレーションシップ・マッピング・タイプやEJB 2.n CMP Beanはサポートされません。 |
問合せの基準となる属性のみを設定し、その他の属性はすべてnull
に設定します。デフォルトでは、サンプル・インスタンス内のnull
、ゼロ(0)、空の文字列およびFALSE
を含む属性は無視されます。QueryByExamplePolicy
(「QueryByExamplePolicyの定義」を参照)を指定することで、この値リストを変更し、例による問合せの他のオプションを定義できます。
例による問合せでは、AND
演算子を使用して属性の比較を結合します。デフォルトでは、サンプル・インスタンスの属性値と、EQUALS
演算子を使用する候補オブジェクトの対応する値を比較します。QueryByExamplePolicy
を使用して、この動作を変更できます。
ReadAllQuery
とReadObjectQuery
には、サンプル・オブジェクト・インスタンスを使用した選択基準を指定できる、setExampleObject
メソッドおよびsetQueryByExamplePolicy
メソッドが用意されています。
詳細および例は、109.2.1.4項「例による問合せを使用したオブジェクトの読取り」を参照してください。
Oracle JDeveloper、TopLink WorkbenchまたはJavaを使用し、TopLink APIを使用して、問合せを作成できます。
問合せには、渡された引数に基づいて暗黙的に作成され、1ステップで実行されるもの(たとえば、108.6項「セッション問合せ」で説明されているセッション問合せ)と、ユーザーが明示的に作成、構成および実行するもの(たとえば108.7項「データベース問合せ」)があります。
詳細は、次を参照してください。
TopLinkでは、表108-2にまとめたセッション
APIを使用して、ほとんどの問合せを実行できます。
表108-2 問合せの実行に使用するセッション・メソッド
問合せのタイプ | セッション・メソッド | 長所と短所 |
---|---|---|
|
|
長所: オブジェクトに対して一般的なデータ・ソース操作を実行するには最も手軽な方法です。 短所: 問合せの実行とその結果を制御できる柔軟性の点で劣り、頻繁に実行する問合せでは非効率的です。 |
|
|
長所: 構成および実行に関して最も柔軟性に優れています。名前付き問合せに共通の効率性という利点があります。 短所: |
|
|
長所: マップされていないデータに直接操作を適用できる便利な方法です。 短所: 問合せの実行とその結果を制御できる柔軟性が最も低く、生のデータ結果についてアプリケーションでより多くの処理を行う必要があります。 |
注意: すべてのデータ・ソース操作は作業ユニットを使用して実行することをお薦めします。これがトランザクション、同時実行性および参照制約を管理する最も効率のよい方法です。詳細は、第113章「TopLinkトランザクションの概要」を参照してください。または、セッションAPIを直接使用して作業ユニット外で問合せを実行することもできますが、その場合は、トランザクション、同時実行性および参照制約をアプリケーション側で管理する責任が増大します。 |
セッション問合せを実行すると、TopLinkではDescriptorQueryManager
問合せが実行されます。詳細は、108.13項「ディスクリプタ問合せマネージャ問合せ」を参照してください。
EJB 2.n CMP Beanで適切なファインダ・メソッドをコールする場合は、EJB 2.n CMPファインダを実行します。詳細は、108.15項「EJB 2.n CMPファインダ」を参照してください。
警告: 検証されていないSQL文字列がメソッド(たとえば |
詳細は、次を参照してください。
通常、TopLinkの問合せはJavaオブジェクトを結果セットとして返します。TopLink問合せでは、次のいずれかを返すことができます。
全体オブジェクト(すべての属性に移入済で、オブジェクトがキャッシュに反映済の状態)
オブジェクトのコレクション(108.5.1項「コレクション問合せの結果」を参照)
レコードのコレクション
レポートのサマリー
部分オブジェクト(指定した属性にのみ移入済で、オブジェクトはキャッシュに反映されていない状態。108.5.2項「レポート問合せの結果」を参照)
オブジェクトのストリーム(108.5.3項「ストリームとカーソルの問合せの結果」を参照)
EJB(108.15項「EJB 2.n CMPファインダ」を参照)
コレクションとは、Collection
またはMap
のインスタンス内に格納されたJavaオブジェクトのグループです。
デフォルトでは、複数のオブジェクトを返す問合せは、その結果をVector
に返します。
問合せ結果をCollection
またはMap
の任意の具象インスタンスに返すように、TopLinkを構成できます。
コレクションの結果は、TopLinkのすべての問合せタイプでサポートされています。
コレクション問合せの結果の構成と処理の詳細は、109.10項「コレクション問合せの結果の処理」を参照してください。
ReportQuery
(部分オブジェクト問合せの一種)は、データベースのレポート関数、およびプラットフォームでサポートされている機能を使用して選択したオブジェクトのサマリー・データを返します。レポート問合せではオブジェクトではなくデータが返されますが、返されたデータをオブジェクト・レベルで問い合せたり、指定したりすることができます。
デフォルトでは、ReportQuery
は、ReportQueryResult
オブジェクトのコレクション(108.5.1項「コレクション問合せの結果」を参照)を1つ返します。コレクションは1つのデータベース行に返されます。ReportQuery
APIを使用して、ReportQuery
がその結果を返す方法を構成できます。詳細は、109.11項「レポート問合せの結果の処理」を参照してください。
詳細は、次を参照してください。
ストリームとはコレクションのビューであり、ファイル、デバイス、Vector
などです。ストリームを使用すると、コレクションの要素に一度に1つずつ順にアクセスできます。これにより、1つのコレクションの全オブジェクトが同時にストリームに含まれることのないストリーム・クラスの実装が可能になります。
大きな結果セットは、収集して処理する際に、リソースを大量に消費します。パフォーマンスを向上させ、クライアントが返された結果をより確実に制御できるようにするには、カーソルまたはストリームを使用するようTopLink問合せを構成します。
カーソルとストリームは、DataReadQuery
およびReadAllQuery
のすべてのサブクラスでサポートされています。
詳細は、111.11項「カーソルとストリームの問合せ結果の処理」を参照してください。
セッションには、表108-3に示すオブジェクト操作を実行するための問合せメソッドがあります。
表108-3 セッション・オブジェクト問合せのサマリー
セッション・タイプ | 作成 | 読取り | 更新 | 削除 |
---|---|---|---|---|
|
registerObject |
|
なし |
|
|
なし |
なし |
なし |
なし |
|
なし |
|
なし |
なし |
|
|
|
|
|
注意: すべてのデータ・ソース操作は作業ユニットを使用して実行することをお薦めします。これがトランザクション、同時実行性および参照制約を管理する最も効率のよい方法です。詳細は、第113章「TopLinkトランザクションの概要」を参照してください。 |
これらのメソッドでは、次の入力パラメータに基づいてDatabaseQuery
を暗黙的に作成して実行し、Object
またはObject
コレクションを返します。
参照Class
(問合せでアクセスするオブジェクトのClass
)
参照Class
およびCall
参照Class
およびExpression
主キーが設定されたサンプル・オブジェクト
これらのメソッドは、オブジェクトに対して最も一般的なデータ・ソース操作を実行するために手軽な方法です。
警告: 検証されていないSQL文字列をメソッドに渡すことを許可すると、SQLインジェクション攻撃に対してアプリケーションが脆弱になります。 |
すべての構成可能オプションを使用して問合せを詳細に設定し、最適化するには、該当するDatabaseQuery
を直接使用する必要があります。詳細は、108.7項「データベース問合せ」を参照してください。
詳細は、109.1項「セッション問合せの使用」を参照してください。
読取り問合せでは、指定した選択基準に一致するObject
の最初のインスタンスを返し、すべて読取り問合せでは、そのようなインスタンスをすべて返します。
また、主キーを設定してドメインObject
を渡すと、TopLinkでは、そのオブジェクトを選択する読取り問合せを構成して実行します。これは、例による問合せの1つの形式です。例による問合せの詳細は、108.2.8.6項「例による問合せ」を参照してください。
詳細は、109.1.1項「セッション問合せを使用したオブジェクトの読取り方法」を参照してください。
オブジェクトは作業ユニットを使用して作成および更新することをお薦めします。これがトランザクション、同時実行性および参照制約を管理する最も効率のよい方法です。詳細は、第113章「TopLinkトランザクションの概要」を参照してください。
ただし、セッション問合せを使用してオブジェクトを作成および更新することもできます。このセッション問合せは、ユーザー設定項目など、リレーションシップを持たない単純な非ビジネス・オブジェクト・データを管理する際に、データベースで直接オブジェクトを変更できる便利な方法です。
オブジェクトが新規であることがわかっている場合は、insertObject
メソッドを使用することで、TopLinkでの存在チェックを省略できます。オブジェクトが新規かどうかわかっていない場合は、updateObject
、writeObject
またはwriteAllObject
メソッドを使用します。必要に応じ、TopLinkにより存在がチェックされます。
書込みセッション問合せを実行すると、オブジェクトとその私有部分の両方がデータベースに書き込まれます。この動作を管理するには、対応するDatabaseQuery
を使用します(108.7.3.7項「オブジェクト・レベルの変更問合せと私有部分」を参照)。
Session
のメソッドdeleteObject
を使用すると、特定のオブジェクトを削除できます。SessionのメソッドdeleteAllObjects
を使用すると、オブジェクトのコレクションを削除できます。指定された各オブジェクトとその私有部分のすべてが削除されます。deleteAllObjects
の場合、1つのトランザクションですべての削除が実行されます。
詳細は、109.1.2項「セッション問合せを使用したオブジェクトの作成、更新および削除方法」を参照してください。
すべてのセッション・タイプでは、次のいずれかのタイプのDatabaseQuery
をとるexecuteQuery
メソッドを使用できます。
DatabaseQuery
のメソッドsetCall
を使用すると、SQL(ストアド・プロシージャおよびストアド・ファンクションを含む)、EJB QL問合せおよびEISインタラクションなどの様々なデータ・ソースのオプションに対応した、独自のCall
を定義できます。詳細は、108.9項「コール問合せ」を参照してください。
DatabaseQuery
のメソッドsetSelectionCriteria
を使用すると、TopLinkのExpression
を使用して、選択基準を指定できます。詳細は、108.2.6項「TopLinkの式」を参照してください。
詳細は、109.2項「DatabaseQuery問合せの使用」を参照してください。
ObjectLevelReadQuery
を使用すると、データ・ソースに問い合せ、指定した選択基準に一致するObject
インスタンスを返すことができます。この項の内容は次のとおりです。
詳細は、109.2.1項「DatabaseQueryを使用したオブジェクトの読取り方法」を参照してください。
ReadAllQuery
を使用すると、データ・ソースに問い合せ、指定した選択基準に一致するすべてのオブジェクトのCollection
を返すことができます。
デフォルトでは、ObjectLevelReadQuery
が、読み取られたオブジェクトのすべての属性を返します。
選択したオブジェクトの、特定の属性のみを必要とする場合、ObjectLevelReadQuery
のメソッドaddPartialAttributes
を使用して部分オブジェクト問合せを作成できます。このメソッドを使用すると、オブジェクトが、指定した属性にのみ移入されて戻されるため、問合せのパフォーマンスが向上します。
アプリケーションでは、部分オブジェクト問合せを使用して、さらに選択を行うためのリストを作成することがよくあります。たとえば、40歳を超える全従業員の名前と住所を調べる問合せでは、オブジェクト(従業員)を部分的に表すデータ(名前と住所)のリストが返されます。通常は、次にこのリストを提示して、ユーザーがリストから必要なオブジェクトを1つ以上選択できるようにします。TopLinkでは常に主キー属性が組み入れられるため(部分属性として追加していない場合でも)、後で完全なオブジェクトを取得するのが簡単になります。
部分オブジェクト問合せを使用する際は、次の点を考慮してください。
部分オブジェクトの編集とキャッシュはできません。
指定されていない属性はnull
のままになります。
同じタイプの部分属性を2つ持つことはできません。
問い合せるクラスと同じタイプの部分属性は追加できません。
選択したオブジェクトの、特定の属性のサマリー情報のみを必要とする場合、ReportQuery
(108.7.5項「レポート問合せ」を参照)を使用するとより効率的です。
詳細は、109.2.1.2項「部分オブジェクト問合せを使用したオブジェクトの読取り」を参照してください。
データが読取り専用であることがわかっている場合は、問合せを読取り専用として指定することでパフォーマンスを向上できます。これにより、問合せによって返されるオブジェクトが不変であることがTopLinkに通知されます。
詳細は、次を参照してください。
結合読取りは、クラスの単一問合せにより、そのクラスのインスタンスおよび関連オブジェクトのインスタンスを作成するデータが戻されるようにする、問合せ最適化機能です。この機能を使用し、データベース・アクセスを減少させることによって、問合せのパフォーマンスを向上できます。デフォルトでは、リレーションシップは結合読取りされません。すなわち、各リレーションシップは、インダイレクション(遅延ロード)を使用している場合はアクセス時に別々にフェッチされ、インダイレクションを使用していない場合はアクセス時に独立したデータベース問合せとしてフェッチされます。詳細は、17.2.4項「インダイレクション(遅延ロード)」を参照してください。
結合読取りをReadObjectQuery
およびReadAllQuery
とともに使用して、表108-4に示すマップされたリレーションシップを結合できます。結合読取りは、その他のリレーションシップ・マッピングでは現在サポートされていません。
表108-4 マッピング・タイプ別の結合読取り
Query | マッピング・タイプ |
---|---|
|
|
|
|
結合読取りでは、複数のネステッド・リレーションシップを結合することを指定できます。ネステッド結合は、式(110.2.7項「結合リレーションシップと複雑なリレーションシップを表す式」を参照)を使用して表現されます。
外部結合も、式の外部結合APIを使用することで、結合読取りとともに使用できます。外部結合を使用していない場合、1対1のリレーションシップがないか1対多のリレーションシップが空のオブジェクトが、結果セットからフィルタ処理されます。また、継承先サブクラスを外部結合できるようにオブジェクト・レベルの読取り問合せを構成すると、クラスごとに問合せをする負荷を回避できます。表108-4に示されているいずれかのマッピングのuseInnerJoinFetch
またはuseOuterJoinFetch
メソッドを使用して、内部結合または外部結合を指定することもできます。
結合読取りはカスタムのSQLまたはストアド・プロシージャで使用することができますが、問合せでは、すべての結合読取りオブジェクトを作成するために必要なデータがすべて戻されるようにする必要があります。結果セットに同じ表またはフィールドが複数含まれている場合は、これらが戻される順序は、TopLinkで生成される表順序と共通にする必要があります。
詳細は、次を参照してください。
1対多のリレーションシップまたは共有されている1対1のリレーションシップが結合される場合、結合読取りは、重複データを返すことがあります。TopLinkでは、オブジェクト結果内の重複結果を正しくフィルタ処理しますが、重複データは、依然としてデータベースからフェッチされてしまい、このため、特に複数の1対多のリレーションシップが結合されている場合には、パフォーマンスを低下させる可能性があります。一般的に、バッチ読取りは、結合読取りの代替として使用できますが、重複データをフェッチする必要がない点でより優れています。
1対多の結合は、多くの場合、スケーラビリティがよくないため、注意しながら使用することをお薦めします。
ReadObjectQuery
の場合は、主な負荷はSQL実行にあるため、1対多の結合のパフォーマンスは、結合を使用しない問合せよりも通常高くなります。
これに対して、ReadAllObjectQuery
の場合、主な負荷は行のフェッチであり、これはさらに結合の重複データにより増大するため、1対多の結合のパフォーマンスは、多くの場合に行うバッチ読取りよりも非効率になります(ただし、1対多の結合は、1つずつオブジェクトを読み取るよりは高効率です)。
これは、主に、1対多の結合では重複データが読み取られるためです。つまり、各ソース・オブジェクトのデータがターゲット・オブジェクトごとに重複化されるためです。これは、1対多リレーションシップのサイズとソース・オブジェクトの行のサイズによっては、非常に非効率的です。特に、ソース・オブジェクトにラージ・オブジェクト(LOB)がある場合は、そうです。
複数またはネストの1対多の結合を同一の問合せ内で使用する場合は、問題は複雑になります。ソース・オブジェクトの行はn*m回重複し、各ターゲット・オブジェクトはそれぞれn回およびm回重複します。これは、パフォーマンス上大きな問題となります。
空のコレクションを処理するには、外部結合を使用する必要があり、このため問合せを行うことによってデータベースに非常に負担をかけることになります。バッチ読取りには、必要なデータのみを返し、外部結合を行う必要がないという利点があります。
すべてのオブジェクトを読み取るアプリケーションにおいてリレーションシップの問合せを最適化するには、バッチ読取りを使用することをお薦めします。
詳細は、次を参照してください。
DataLevelReadQuery
を使用すると、データ・ソースに問い合せ、指定した選択基準に一致するObject
インスタンスを返すことができます。この項の内容は次のとおりです。
詳細は、109.2.4項「DatabaseQueryを使用したデータの読取り方法」を参照してください。
警告: 検証されていないSQL文字列を |
DataReadQuery
を使用すると、結果セットを表すRecord
オブジェクトのCollection
を返す選択SQL文字列を実行できます。
DirectReadQuery
を使用すると、結果セットを表す値のCollection
が戻されたデータから1列(フィールド)を読み取ることができます。
ValueReadQuery
を使用すると、単一データ値(1つのフィールド)を読み取ることができます。単一データ値が戻されます。または、行が戻されない場合は、nullが戻されます。
ObjectLevelModifyQuery
を使用すると、データ・ソースに問い合せ、オブジェクトを作成、更新および削除できます。この項の内容は次のとおりです。
詳細は、109.2.2項「DatabaseQueryを使用したオブジェクトの作成、更新および削除方法」を参照してください。
注意: オブジェクトは、TopLinkUnitOfWork を使用して作成および更新することをお薦めします。これがトランザクション、同時実行性および参照制約を管理する最も効率のよい方法です。詳細は、第113章「TopLinkトランザクションの概要」を参照してください。 |
オブジェクトが新規かどうかわからない場合は、WriteObjectQuery
を使用します。TopLinkでは、挿入または更新を実行するかどうかを判断する際に必要上、存在チェックを実行します。
オブジェクトが既存かどうかがわからない場合は、UpdateObjectQuery
(108.7.3.2項「UpdateObjectQuery」を参照)またはInsertObjectQuery
(108.7.3.3項「InsertObjectQuery」を参照)を使用することで存在チェックを回避できます。
変更対象のオブジェクトが存在することがわかっている場合は、UpdateObjectQuery
を使用して、TopLinkでの存在チェックを省略できます。
オブジェクトが新規であることがわかっている場合は、InsertObjectQuery
を使用することで、TopLinkでの存在チェックを省略できます。
引数として特定のオブジェクトを1つ持つDeleteObjectQuery
を作成することで、特定のオブジェクトを削除できます。
UpdateAllQuery
では、式を使用して、オブジェクトをメモリーにロードせずに(オブジェクト・レベルで)オブジェクトのセットを更新できます。具体的な値の更新、または相対値での更新ができます。たとえば、値を5に設定したり、5%ずつ増分するように設定できます。
詳細は、109.2.3.1項「UpdateAllQueryの使用」を参照してください。
複数のオブジェクトを削除するには、DeleteAllQuery
を作成し、そのsetObjects
メソッドを使用して、削除対象の特定のオブジェクトのコレクションを構成します。DeleteAllQuery
のメソッドsetReferenceClass
を使用して、削除対象のオブジェクトの参照クラスを構成します。指定された各オブジェクトが削除されますが、その私有部分は削除されません。
DeleteAllQuery
の場合、1つのトランザクションですべての削除が実行されます。
詳細は、109.2.3.2項「DeleteAll問合せの使用」を参照してください。
オブジェクトの作成または更新のDatabaseQuery
を実行すると、デフォルトではオブジェクトとその私有部分の両方がデータベースに書き込まれます。私有部分を更新しない問合せを作成するには、DatabaseQuery
のメソッドdontCascadeParts
を使用します。このメソッドは、次の目的で使用します。
オブジェクトのダイレクト属性のみが変更されたことがわかっている場合に、パフォーマンスを向上させること。
独立した新規オブジェクトの大きなグループを作成する場合に、参照整合性の依存関係を自分で解決すること。
注意: 作業ユニットでは参照整合性が内部的に解決されるため、作業ユニットを使用してデータ・ソースに書き込む場合はこのメソッドは不要です。詳細は、第113章「TopLinkトランザクションの概要」を参照してください。 |
DataModifyQuery
を使用すると、データ・ソースに問い合せ、選択を行わないSQL文を実行できます。これは、Session
のメソッドexecuteNonSelectingCall
と同等です。
詳細は、109.2.5項「DatabaseQueryを使用したデータの更新方法」を参照してください。
オブジェクトのセットの、特定の属性を要約(または集計)する場合、ReportQuery
を使用できます。
ReportQuery
は、オブジェクトのセットおよび関連オブジェクトを基にサマリー・データを戻します。つまり、オブジェクトに関するデータを戻します。また、複数のオブジェクトを戻すこともできます。ReportQuery
では、オブジェクト・レベルでのデータの問合せおよび指定ができます。レポート問合せを作成するには、検索基準、含める必要のあるオブジェクト情報およびデータの要約方法を指定します。
たとえば、社内の全従業員の平均年齢を計算するレポート問合せを作成できます。このレポート問合せの対象となるのは特定のオブジェクト(従業員)ではなく、オブジェクトに関するサマリー情報(従業員の平均年齢)です。
ReportQuery
は、次の目的で使用します。
オブジェクトの属性とその関連オブジェクトの属性のサブセットを指定すること。これにより、軽量の情報の問合せが可能になります。
選択基準と順序付けの基準を表す、オブジェクトレベルの複雑な式を作成すること。
SUM
、MIN
、MAX
、AVG
、COUNT
など、(プラットフォームでサポートされている)データ・ソース集計関数を使用すること。
式を使用してデータをグループ化すること。
各ReportQueryResult
で主キー属性を要求すること。これにより、軽量の結果から実際のオブジェクトを簡単に要求できるようになります。
ReportQuery
は、データ・ソースのレポート機能(存在する場合)を利用できるため、最も効率的な形態の部分オブジェクト問合せ(108.7.1.3項「部分オブジェクト問合せ」を参照)です。部分オブジェクト問合せを実行する場合にはReportQuery
を使用することをお薦めします。
ReportQuery
APIは、ReportQueryResult
オブジェクトのコレクションを返します。このオブジェクトは、構造と動作の点でRecord
やMap
に似ています。詳細は、108.5.2項「レポート問合せの結果」を参照してください。
詳細は、次を参照してください。
readAllObjects
のようなセッション問合せメソッド(108.6項「セッション問合せ」を参照)を使用すると、TopLinkでは、そのタスクを実行するために必要なその他のオブジェクトを作成する、対応するReadAllQuery
を作成します。readAllObjects
メソッドの実行が終了すると、これらのオブジェクトは破棄されます。このセッション・メソッドをコールするたびに、これらの関連オブジェクトが再作成され、一度使用された後、破棄されます。
または、DatabaseQuery
(108.7項「データベース問合せ」を参照)は、作成後に、ディスクリプタ・レベル(119.7項「ディスクリプタ・レベルでの名前付き問合せの構成」を参照)またはセッション・レベル(89.13項「セッション・レベルでの名前付き問合せの構成」を参照)で名前付きで保存することもできます。
TopLinkでは、名前付き問合せは1回のみプリコンパイルされ、以後、名前付き問合せ(とその基礎となるすべての関連オブジェクト)は、効率的に再利用でき、頻繁に実行する操作に適用できます。
セッション
API(109.3項「名前付き問合せの使用」を参照)を使用すると、これらの名前付き問合せを必要な引数付きで実行できます。
名前付き問合せを使用する方がよい場合
頻繁に実行するかなり複雑な問合せの場合は、問合せを名前付き問合せにすることを検討してください。
問合せがプロジェクトにおいてグローバルな場合は、名前付き問合せをセッション・レベル(89.13項「セッション・レベルでの名前付き問合せの構成」を参照)に構成します。
問合せがClass
においてグローバルな場合、またはCMPファインダを構成する場合は、名前付き問合せをディスクリプタ・レベル(119.7項「ディスクリプタ・レベルでの名前付き問合せの構成」を参照)に構成します。ディスクリプタ・レベルでの問合せの構成の詳細は、108.13項「ディスクリプタ問合せマネージャ問合せ」を参照してください。
問合せが非常に複雑な場合は、リダイレクト問合せという特別な形式の名前付き問合せを使用して、独自のstaticメソッドに問合せの実行を委譲できます。リダイレクト問合せの詳細は、108.10項「リダイレクト問合せ」を参照してください。
名前付き問合せを使用しない方がよい場合
まれにしか使用されない問合せは、必要に応じて作成する方が効率的です。特定の問合せをほとんど使用しない場合、セッションの起動時にその問合せを作成して格納するだけの価値がないこともあります。
すべてのセッション・タイプでは、次のいずれかのCall
タイプを取るexecuteSelectingCall
およびexecuteNonSelectingCall
メソッドを使用できます。
Call
は、DatabaseQuery
のコンテキストで実行することもできます。DatabaseQuery
の詳細は、108.7項「データベース問合せ」を参照してください。
警告: 検証されていないSQL文字列をメソッド(たとえば |
SQLコールでは、リレーショナル・データベースのフィールドにアクセスします。TopLinkでは、次のSQLコールがサポートされています。
StoredProcedureCall(PLSQLStoreProcedureCall
を含む)
Call
API(またはSQL文字列表記規則)を使用すると、入力、出力および入出力パラメータを指定でき、入力および入出力パラメータに値を割り当てることができます。
ディスクリプタReturningPolicy
を使用すると、TopLinkでパラメータに書き込むか、データベースによって生成された値を取得するか、またはその両方を行うかを制御できます。詳細は、119.27項「リターン・ポリシーの構成」を参照してください。
SQLCall
を使用すると、任意のSQL文を指定して、データ・ソースでそれを実行できます。
警告: 検証されていないSQL文字列をメソッドに渡せるようにすると、SQLインジェクション攻撃に対してアプリケーションが脆弱になります。 |
詳細は、109.4項「SQLCallの使用」を参照してください。
ストアド・プロシージャは、複数の手続き型言語(Procedural Language/Structured Query Language(PL/SQL)など)で構成され、データベースに名前付きで保存されます。ほとんどのリレーショナル・データベースが、ストアド・プロシージャをサポートします。
ストアド・プロシージャを起動すると、ロジックを実行してデータ・ソースからデータにアクセスできます。
StoredProcedureCall
では、実行エラーの検出と、入力パラメータ、出力パラメータおよび入出力パラメータの指定ができます。ただし、ストアド・プロシージャでは戻り値を返しません。
詳細は、109.5項「StoredProcedureCallの使用」を参照してください。
ストアド・ファンクションは、ストアド・プロシージャのすべての機能のみでなく、値を返す機能も提供するOracleデータベースの機能です。
StoredFunctionCall
では、StoredProcedureCall
のすべての機能のみでなく、戻り値のフィールド名を指定できます。
詳細は、109.6項「StoredFunctionCallの使用」を参照してください。
TopLinkでは、EJB QLコールは、EJB QL文字列を表します。EJBQLCall
オブジェクトは、データベース起動の抽象オブジェクトです。EJB QLコールは、セッションから直接実行することも、あるいはDatabaseQuery
のコンテキストで実行することもできます。
詳細は、次を参照してください。
Java EE Connector Architecture(JCA)アダプタを介してリモートEISに対する問合せを起動するには、Call
のインスタンスであるEISInteraction
を使用します。TopLinkでは、次のEISInteraction
タイプがサポートされています。
これらの各インタラクションには、EISに対して起動する関数を識別する関数インタフェース(ストアド・プロシージャに類似)を指定します。この関数インタフェースには次のものがあります。
関数名
レコード名(関数名と異なる場合)
入力引数のリスト
出力引数のリスト
詳細は、次を参照してください。
IndexedInteraction
では、索引付きレコードを使用して、データをEISと交換します。引数の指定順序は、索引付きレコードに定義されている値の順序と一致している必要があります。
MappedInteraction
では、マップ済レコードを使用して、データをEISと交換します。指定する引数は、名前によって、マップ済レコードのフィールドにマップされます。
XMLInteraction
は、MappedInteraction
に、データをXMLレコードにマップする機能を追加したものです。XMLInteraction
の場合、オプションでルート要素名を指定することもできます。
JCAアダプタがXQuery動的問合せ言語をサポートする場合には、XQueryInteraction
を使用できます。これは、XQuery文字列を指定できるようにしたXMLInteraction
です。
JCAアダプタが問合せ文字列ベースの動的問合せ言語をサポートする場合には、QueryStringInteraction
を使用できます。これは、MappedInteraction
に、動的問合せ文字列を指定する機能を追加したものです。
複雑な問合せロジックに対応するために、リダイレクト問合せを実装できます。これは名前付き問合せで、問合せの実行制御をアプリケーションに委譲します。詳細は、108.8項「名前付き問合せ」を参照してください。
リダイレクト問合せを使用すると、問合せの実装をstaticメソッドとしてコードで定義できます。問合せを起動したときには、コールは指定したstaticメソッドにリダイレクトされます。リダイレクト問合せは、Vector
にパッケージ化された形で自身に渡されるパラメータをすべて受け入れます。
TopLink問合せのほとんどはオブジェクトを直接検索しますが、リダイレクト問合せは一般的に、別のクラスのメソッドを起動して結果を待ちます。リダイレクト問合せを使用すると、複雑な操作(他の方法では問合せフレームワーク内で実行できない操作を含む)を作成して使用することができます。
リダイレクト問合せを使用すると、問合せの起動がユーザーの提供するメソッドに委譲されるため、問合せを引数の値に基づいてどのように実行するのかを動的に決定できます。
リダイレクト問合せを使用すると、次のことが可能になります。
引数に基づいて問合せオプションを動的に構成します(たとえば、順序付けおよび問合せの最適化)。
引数に基づいて選択基準を動的に定義します。
引数として例による問合せオブジェクトまたは式を渡します。
問合せ結果を後処理します。
複数の問合せまたは特別な操作を実行します。
UnitOfWork
で問合せを実行する場合、結果はUnitOfWork
のインスタンスに登録されるため、起動メソッドで取得するのはセッション・キャッシュ内のオブジェクトである必要があります。
リダイレクト問合せを作成するには、QueryRedirector
インタフェースを実装し、この実装を名前付き問合せに設定します。
TopLinkに付属するQueryRedirector
のインスタンスであるMethodBasedQueryRedirector
を利用することをお薦めします。これは、staticメソッドの名前および、このメソッドがパラメータとして定義されているClass
を引数として取ります。名前付き問合せにMethodBasedQueryRedirector
を設定した場合、このインスタンスのinvokeQuery
メソッドをコールするたびに、TopLinkでは、staticメソッドを起動するためにリフレクションをかわりに使用します。
MethodBasedQueryRedirector
を使用する利点は、次のとおりです。
staticメソッドとそのClass
を動的に指定できます。
staticメソッドを提供するクラスでは、QueryRedirector
を実装する必要はありません。
staticメソッドには任意の名前を付けられます。
staticメソッドに対するパラメータを、引数のSession
とVector
のみに限定できます。
詳細は、111.1項「リダイレクト問合せの使用」を参照してください。
デフォルトでは、セッションはオブジェクトの最新バージョンの表示を表し、そのセッションで問合せを実行すると、選択したオブジェクトの最新バージョンが戻されます。
データ・ソースが過去バージョンすなわち履歴バージョンのオブジェクトを保持している場合は、この履歴データにアクセスするようにTopLinkを構成できます(87.6項「履歴セッション」を参照)。
履歴データを利用するようにTopLinkを構成すると、表108-5にまとめた履歴問合せを使用して履歴バージョンにアクセスできます。
注意: フラッシュバック問合せは、ビュー選択をサポートしません。つまり、全サブクラス読取り用のビューの継承ポリシーを持つオブジェクトに対して、フラッシュバック問合せは使用できません。詳細は、16.3項「ディスクリプタと継承」を参照してください。 |
表108-5 履歴問合せ
履歴問合せのタイプ | セッション | キャッシュ | maintainCache をfalseに設定する必要があるか |
現在のバージョンと履歴バージョンの両方についての問合せ |
---|---|---|---|---|
AsOfClauseを持つObjectLevelReadQueryの使用 |
標準脚注1 |
|
○ |
× |
式演算子asOfを持つObjectLevelReadQueryの使用 |
標準脚注1 |
|
× |
○ |
履歴セッションでのObjectLevelReadQueryの使用 |
履歴脚注2 |
|
× |
× |
脚注1 Oracle9i以降のOraclePlatform
またはTopLink HistoryPolicy
を使用したサーバーまたはデータベースのセッション。
脚注2 OraclePlatform
またはTopLink HistoryPolicy
を使用したサーバーまたはデータベースのセッションにより、AsOfClause
付きのacquireHistoricalSession
メソッドを使用して返されたセッション。
ObjectLevelReadQuery
のメソッドsetAsOfClause
で設定したAsOfClause
でObjectLevelReadQuery
を構成することで、オブジェクトの履歴バージョンを問い合せることができます。AsOfClause
には、問合せで使用するすべてのExpression
に適用される時刻を指定します。
このタイプの履歴問合せを使用すると、指定された時刻現在で存在する各オブジェクト・バージョンの静的スナップショットについて問い合せることができます。
注意: オブジェクトの古いバージョンを持つグローバル共有キャッシュが破損することを回避するには、この履歴問合せでObjectLevelReadQuery のメソッドmaintainCache をfalse に設定する必要があります。設定しない場合は、問合せを実行する際に、TopLinkにより例外がスローされます。 |
AsOfClause
を持つObjectLevelReadQuery
の使用方法の詳細および例は、111.2項「履歴問合せの使用」を参照してください。
ObjectLevelReadQuery
(ReadObjectQuery
またはReadAllQuery
など)を使用して、オブジェクトの履歴バージョンについて問い合せることができます。ObjectLevelReadQuery
には、Expression
演算子asOf
を使用する1つ以上の式を指定し、Expression
ごとに時刻を指定します。
このタイプの履歴問合せを使用すると、オブジェクトの現在のバージョンと履歴バージョンの両方を同じ問合せ内で組み合せることができます。
AsOfClause
を持つObjectLevelReadQuery
を構成する際には、AsOfClause
に指定した時刻により、問合せの各Expression
に指定した時刻がオーバーライドされます(108.11.1項「AsOfClauseを持つObjectLevelReadQueryの使用」を参照)。
Expression
の演算子asOf
を持つObjectLevelReadQuery
の使用方法の詳細および例は、111.2項「履歴問合せの使用」を参照してください。
セッションが(該当するOraclePlatform
またはTopLink HistoryPolicy
に基づく)オブジェクトの履歴バージョンを保持する場合は、Session
のメソッドacquireHistoricalSession
でAsOfClause
を渡します。AsOfClause
には、すべての問合せと式に適用する時刻を指定します。
このメソッドにより、指定された時刻現在で存在する各オブジェクト・バージョンの、読取り専用の軽量なスナップショットが返されます。このタイプのセッションで使用されるキャッシュは、グローバル共有キャッシュからは独立しています。このため、ObjectLevelReadQuery
のメソッドmaintainCache
をfalse
に設定する必要はありません。
履歴セッションを持つObjectLevelReadQuery
の使用方法の詳細および例は、111.2項「履歴問合せの使用」を参照してください。
インタフェース・ディスクリプタ(22.2.1.3項「リレーショナル・インタフェース・ディスクリプタの作成」を参照)を定義すると、インタフェースおよび継承階層に対する問合せを実行できます。
詳細は、次を参照してください。
各Descriptor
はDescriptorQueryManager
のインスタンスを所有しており、このインスタンスは次の目的に使用できます。
名前付き問合せの構成(108.13.1項「名前付き問合せの構成方法」を参照)
デフォルトの問合せ実装の構成(108.13.2項「デフォルトの問合せ実装の構成方法」を参照)
追加の結合式の構成(108.13.3項「追加の結合式の構成方法」を参照)
DescriptorQueryManager
には、頻繁に使用する名前付き問合せを保存および取得するためのAPIが用意されています。
詳細は、108.8項「名前付き問合せ」を参照してください。
各Descriptor
のDescriptorQueryManager
では、TopLinkが次のデータ・ソース操作に使用する問合せの実装をカスタマイズできます。
オブジェクトの挿入
オブジェクトの更新
オブジェクトの読取り
すべてのオブジェクトの読取り
オブジェクトの削除
たとえば、ストアド・プロシージャを使用してオブジェクトを挿入する必要がある場合、DescriptorQueryManager
のオブジェクト挿入問合せで使用されるデフォルトのSQLCall
をオーバーライドできます。
任意のClass
に対する問合せを実行すると、TopLinkでは、DescriptorQueryManager
を参照して、指定のデータ・ソース操作を実行する方法が決定されます。
この機能の用途は、TopLink動作の拡張、非リレーショナル・データへのアクセスまたはストアド・プロシージャやカスタマイズされたSQLコールの使用など、様々です。
警告: 検証されていないSQL文字列をメソッドに渡せるようにすると、SQLインジェクション攻撃に対してアプリケーションが脆弱になります。 |
これらのデフォルトの問合せ実装のカスタマイズ方法の詳細と例は、次を参照してください。
あるクラスで実行する各問合せに自動的に式を追加するよう、DescriptorQueryManager
を構成することができます。たとえば、特定のクラスの有効なインスタンスに対してデータ・ソースをフィルタ処理する式を追加できます。
詳細は、111.7項「その他の結合式の追加」を参照してください。
TopLinkをOracleデータベースとともに使用する場合は、TopLinkアプリケーション内から次のOracle固有の問合せ機能を使用できます。
Oracleでは、データベース・サーバーのSQLオプティマイザの動作を変更できる、ヒントというSQL問合せの追加機能を指定できます。これを使用すると、通常オプティマイザで行われる設定を変更できます。ヒントを使用して、結合文の結合順序やSQLコールの最適化方法などを指定します。
ヒントを指定するには、DatabaseQuery
のメソッドsetHintString
を使用します。
詳細は、次を参照してください。
使用しているデータベースのパフォーマンス・チューニング・ガイドおよびリファレンス
Oracleデータベースの階層問合せメカニズムを使用すると、階層順序に基づいてデータベースの行を選択できます。たとえば、特定の従業員の行、その従業員が管理する人々の行、その人々に管理される従業員の行などの順序で読取りを行う問合せを設計できます。
DatabaseQuery
のサブクラスReadAllQuery
のメソッドsetHierarchicalQueryClause
を使用して、階層問合せ句を指定します。DatabaseQuery
問合せの詳細は、108.7項「データベース問合せ」を参照してください。
Oracle階層問合せ句でのReadAllQuery
の構成の詳細は、111.9.2項「階層問合せの使用方法」を参照してください。
TopLinkをOracle9iデータベース以降とともに使用する場合、特別な履歴セッションを取得できます。このセッションでは、過去の特定時刻までのすべてのオブジェクトが読み取られ、ある期間にどのようにオブジェクトが変更されているかについての条件を付けた読込み問合せを表現できます。
詳細は、108.11項「履歴問合せ」を参照してください。
ストアド・ファンクションは、ストアド・プロシージャのすべての機能を提供するのみでなく値も返せるOracleデータベースのメカニズムです。
詳細は、108.9.1.3項「StoredFunctionCall」を参照してください。
EJBファインダとは、EJB仕様によって定義された問合せです。EJBファインダは、EJB、コレクションおよび列挙値を戻します。ファインダと問合せの違いは、問合せがJavaオブジェクトを返すのに対し、ファインダはEJBを返す点です。TopLink問合せフレームワークでは、エンティティBeanを取得する複雑なファインダを作成して実行できます。
ファインダには、検索基準を定義するファインダ・メソッドが含まれています。ファインダ・メソッドの作成に必要な作業は、コンテナ管理の永続性(CMP)によるBeanファインダを作成するのか、Bean管理の永続性(BMP)によるBeanファインダを作成するのかによって異なります。
CMPファインダの場合、ファインダのAPIメソッド・シグネチャをBeanのHome
インタフェースで定義する必要があります。CMPプロバイダは、ファインダの実際のコード・メカニズムをAPI定義から生成します。
BMPファインダの場合、ファインダ・メソッドの実行に必要なコードを提供する必要があります。
どちらの場合も、ファインダはBeanのHome
インタフェースで定義します。
任意のTopLink問合せ機能を使用してファインダを実装できます。また、CMPおよびBMPエンティティBeanのためにTopLinkに用意されている事前定義ファインダの実装を利用できます。
この項の内容は次のとおりです。
詳細は、111.10項「EJB 2.n CMPファインダの使用」を参照してください。
TopLinkでは、豊富なAPIが用意された事前定義ファインダが実装されています。このAPIを使用すると、実行時に問合せプロパティを動的に指定でき、TopLink問合せ機能を完全に活用できるようになります。
TopLinkでは、次の事前定義ファインダが用意されています。
詳細は、次を参照してください。
表108-6は、TopLink CMP(OC4Jを使用)で使用できる事前定義ファインダを示します。
表108-6にリストしたメソッド名は、TopLinkランタイムで予約されています。
表108-6 事前定義CMPファインダ
メソッド | 引数 | 戻りタイプ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意: ファインダがローカル・ホームに位置している場合、findOneBy が含まれているファインダのEJBObject をEJBLocalObject に置き換えます。 |
これらのファインダは、それぞれ引数のVectorなしで使用することもできます。たとえば、EJBObject findOneByEJBQL(String ejbql)
は有効な動的ファインダですが、EJBObject
の戻りタイプをBeanのコンポーネント・インタフェースに置き換える必要があります。
詳細は、111.10項「EJB 2.n CMPファインダの使用」を参照してください。
表108-7は、oracle.toplink.ejb.bmp.BMPEntityBase
(2.15項「BMPを使用するEJBエンティティBeanのアーキテクチャについて」を参照)を基にBMP EJBを拡張する場合に使用できる事前定義ファインダを示します。
表108-7にリストしたメソッド名は、TopLinkランタイムで予約されています。
表108-7 事前定義BMPファインダ
メソッド | 引数 | 戻りタイプ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EJBファインダの使用方法の詳細は、111.10項「EJB 2.n CMPファインダの使用」を参照してください。
findBy<
CMP-FIELD-NAME
>
(<
CMP-FIELD-NAME
>
はBeanの永続フィールド名)という名前のエンティティBeanのホーム・インタフェースに定義された各ファインダ・メソッドに対して、TopLinkにより、ファインダの実装(TopLinkの式フレームワークを使用したTopLink問合せを含む)が生成されます。戻りタイプが単一のBeanタイプの場合は、TopLinkではReadObjectQuery
が作成されます。戻りタイプがCollection
の場合は、TopLinkではReadAllQuery
が作成されます。
エンティティのホームでのファインダの定義が必要なことは変わりませんが、ejb-jar.xml
ファイルでファインダを宣言する必要がなくなります。
詳細は、111.10.1項「ファインダの作成方法」を参照してください。
DatabaseQuery
を使用するファインダを使用すると、デプロイ時ではなく実行時に生成する動的問合せを作成できます。
TopLinkには、DatabaseQuery
をとるファインダに加えて、特定のタイプのEJBをすべて返すデフォルトのfindAll
ファインダも用意されています。他の動的ファインダと同様に、findAll
という名前もTopLinkランタイムで予約されています。
詳細は、108.7項「データベース問合せ」を参照してください。
DatabaseQuery
をとるTopLink事前定義ファインダの詳細は、108.15.1項「事前定義ファインダ」を参照してください。
DescriptorQueryManager
またはSession
に保存された名前付きDatabaseQuery
を使用するファインダを使用すると、頻繁に実行する問合せを効率的に再利用できます。
詳細は、次を参照してください。
TopLinkでは、Java Object
の主キー・クラスをとる事前定義ファインダを実装しています。
EJB 2.0および2.1の仕様により、コンテナは各BeanのHome
インタフェースでfindByPrimaryKey
コールを実装する必要があるため、このファインダをBeanから削除しないでください。
詳細は、108.15.1項「事前定義ファインダ」を参照してください。
TopLinkのExpression
を使用したファインダを使用すると、次のような利点があります。
Javaコードでの標準的な問合せがバージョン制御可能
複雑な操作のほとんどを単純化可能
EJB QLの場合よりも充実した問合せ機能
式を使用すると、オブジェクト・モデルに基づいてファインダの検索基準を指定できるため、多くの場合、式はファインダの構成に最も適した方法です。
詳細は、108.2.6項「TopLinkの式」を参照してください。
Expression
をとるTopLink事前定義ファインダの詳細は、108.15.1項「事前定義ファインダ」を参照してください。
DatabaseQuery
のメソッドsetSelectionCriteria
を使用することで、DatabaseQuery
をとるファインダでもExpression
を使用できます。DatabaseQueryをとるTopLink事前定義ファインダの詳細は、108.15.4項「DatabaseQueryファインダ」を参照してください。
TopLinkでは、EJB QLがサポートされています。EJB QLファインダを使用すると、EJB QL文字列を問合せの実装として指定できます。
EJB QLには次のような利点があります。
問合せのEJB 2.0および2.1標準です。
ほとんどの問合せの構成に使用できます。
EJB QLを使用すると、依存オブジェクト問合せを実装できます。
EJB QLの短所は、複雑な問合せを構成する場合に使用方法が難しいことです。
TopLinkにおけるEJB QLのサポートの詳細は、108.2.8項「問合せ言語」を参照してください。
EJB QLをとるTopLink事前定義ファインダの詳細は、108.15.1項「事前定義ファインダ」を参照してください。
SQLを使用してファインダを定義すると、次のような利点が得られます。
EJB QLやTopLinkのExpression
を使用したときには表現できないロジックを実装できます。
TopLinkで生成されたSQLのかわりに、ストアド・プロシージャを使用できます。
カスタムSQLによってパフォーマンスが向上する場合があります。
SQLファインダには次のような短所もあります。
複雑なカスタムSQL文を記述すると、データベースの表が変更された場合に、大幅なメンテナンス作業が必要になります。
SQLをハード・コードすると、他のデータベースへの移植性が制限されます。
SQL文字列に対する検証が行われません。SQL文のエラーは、実行時まで検出されません。
SELECT
以外の関数にSQLを使用すると、予測できないエラーが発生する可能性があります。
SQLをとるTopLink事前定義ファインダの詳細は、108.15.1項「事前定義ファインダ」を参照してください。
リダイレクト・ファインダを使用すると、任意のヘルパー・クラスでstaticメソッドとして定義されるファインダを実装できます。ファインダを起動したときには、コールは指定したstaticメソッドにリダイレクトされます。
リダイレクト問合せは複雑であり、問合せを定義するための余分なヘルパー・メソッドも必要になります。しかし、リダイレクト問合せは複雑なロジックをサポートしているため、実装する必要のあるロジックが、リダイレクト・メソッドがコールされるBeanに関連していない場合には、しばしば最適な方法となります。
詳細は、次を参照してください。
ejbSelectメソッドとは、エンティティBeanインスタンスで内部的に使用することを目的とした問合せメソッドです。抽象Bean自体に指定されるejbSelectメソッドは、ホームまたはコンポーネント・インタフェースでクライアントに直接公開されることはありません。各Beanは抽象として定義され、このようなメソッドを0個以上含むことができます。
ejbSelectメソッドには次の特性があります。
メソッド名に接頭辞としてejbSelect
を付ける必要があります。
publicとして宣言する必要があります。
abstractとして宣言する必要があります。
throws
句にはjavax.ejb.FinderException
を指定する必要がありますが、アプリケーション固有の例外も指定できます。
ejb-jar.xml
ファイルのresult-type-mapping
タグによってejbSelect
メソッドの戻りタイプが決まります。このフラグをRemote
に設定するとEJBObjects
が返され、Local
に設定するとEJBLocalObjects
が返されます。
ejbSelect
メソッド定義の書式は次のようになります。
public abstract type ejbSelect<METHOD>(...);
ejbSelect
問合せの戻りタイプは、ejbSelect
が起動されるエンティティBeanのタイプに限定されません。かわりに、コンテナ管理のリレーションシップまたはコンテナ管理のフィールドに対応する任意のタイプを返すことができます。ただし、次の例外を伴います。ejbSelect
メソッドの戻りタイプがjava.util.Collection
の場合、その結果はセレクタが定義されたエンティティ・タイプである必要があります。
選択メソッドは、それが起動されるエンティティBeanインスタンスのアイデンティティに基づいていませんが、エンティティBeanの主キーを引数として使用できます。その場合、有効範囲を特定のエンティティBeanインスタンスに論理的に設定した問合せが作成されます。
ejbSelect
メソッドでのTopLink問合せの使用方法の詳細は、111.10項「EJB 2.n CMPファインダの使用」を参照してください。
問合せを実行すると、データベースまたはTopLinkのセッション・キャッシュから情報が取得されます。問合せがTopLinkのキャッシュを使用する問合せ方法を構成して、パフォーマンスを最適化することができます。
TopLinkでは、クライアント側のキャッシュを維持し、データベースからの読取り操作が必要になる回数を減らしています。TopLinkでは、データベースに書き込まれたオブジェクトとデータベースから読み取られたオブジェクトをキャッシュし、オブジェクト・アイデンティティを維持します。問合せでキャッシュとデータベースがチェックされる順序は、問合せのパフォーマンスに影響を与えます。デフォルトでは、主キー問合せはデータベースにアクセスする前にキャッシュをチェックします。また、すべての問合せが行からオブジェクトを再作成する前にキャッシュをチェックします。
この項では、問合せとキャッシュの間のリレーションシップを操作する方法について説明します。この項の内容は次のとおりです。
TopLinkアプリケーションのキャッシュには、すでにデータベースから読み取られたオブジェクト、またはデータベースに書き込まれたオブジェクトが保持されます。TopLinkアプリケーションでキャッシュを使用することにより、データベースへのアクセス回数が減少します。データベースへのアクセスには時間がかかり、リソースを消費するため、効果的なキャッシュ方法はアプリケーションを効率化する上で重要です。
キャッシュの構成と使用の詳細は、第102章「キャッシュの概要」を参照してください。
インメモリー問合せは、共有セッション・キャッシュに対して実行される問合せです。インメモリー問合せの構成を注意して行うとパフォーマンスが向上しますが、すべての問合せでインメモリー問合せが効果を発揮するわけではありません。たとえば、主キーを使用した個別オブジェクトの問合せの場合は、通常はインメモリー問合せを使用することでパフォーマンスが向上しますが、主キーを使用しない問合せの場合は向上する可能性が低くなります。デフォルトでは、主キーを使用してシングル・オブジェクトを検索する問合せでは、必要なオブジェクトをまずキャッシュから取得し、オブジェクトがキャッシュに存在しない場合はデータベースで検索を行います。その他すべての問合せタイプの場合は、デフォルトでデータベースを最初に検索します。特定の問合せをインメモリー・キャッシュまたはデータベース、あるいはその両方に対して実行するよう指定できます。インメモリー問合せを使用すると、問合せをデータベースではなくキャッシュに対して実行することができます。
注意: インメモリー問合せから順序付けされた結果は得られません。順序付けはインメモリー問合せではサポートされていないためです。 |
インメモリー問合せは次のリレーションシップをサポートします。
1対1
1対多
多対多
集約コレクション
ダイレクト・コレクション
注意: デフォルトでは、リレーションシップ自体がメモリー内に存在しないと、インメモリー走査は行われません。必ずすべてのValueHolderをトリガーし、インメモリー問合せがリレーションシップ全体で機能するようにしてください。 |
この項の内容は次のとおりです。
ReadObjectQuery
メソッドとReadAllQuery
メソッドを使用して、問合せレベルで、インメモリー問合せでのキャッシュの使用方法を構成できます。
checkCacheByPrimaryKey
: デフォルトの設定です。読取り問合せに少なくとも主キーを比較する式が含まれている場合、メモリー内のオブジェクトに対して式を処理すると、キャッシュ・ヒットを取得できます。
checkCacheByExactPrimaryKey
: 読取り問合せに主キーのみを比較する式が含まれている場合、メモリー内のオブジェクトに対して式を処理すると、キャッシュ・ヒットを取得できます。
checkCacheThenDatabase
: 任意の読取り問合せを構成し、データベースにアクセスする前にキャッシュを完全にチェックすることができます。
checkCacheOnly
: 任意のすべて読取り問合せを構成し、(作業ユニットのキャッシュではなく)親セッション・キャッシュのみをチェックして、データベースにアクセスせずに親セッション・キャッシュから結果を返すことができます。
conformResultsInUnitOfWork
: 任意の読取り問合せまたはすべて読取り問合せを作業ユニットのコンテキスト内で構成し、作業ユニット内でオブジェクトに加えられた変更に結果を一致させることができます。これには、新規オブジェクト、削除されたオブジェクト、および変更されたオブジェクトが含まれます。一致させるときの制限の詳細は、115.4項「一致する問合せおよびディスクリプタの使用」を参照してください。
または、ObjectLevelReadQuery
のメソッドsetCacheUsage
を使用して該当するObjectLevelReadQuery
フィールドを渡すことで、キャッシュの使用方法を構成できます。ObjectLevelReadQuery
フィールドには、CheckCacheByPrimaryKey
、CheckCacheByExactPrimaryKey
、CheckCacheThenDatabase
、CheckCacheOnly
、ConformResultsInUnitOfWork
またはDoNotCheckCache
があります。
インメモリー問合せでは、Expression
メソッド(表108-8を参照)とExpressionMath
メソッド(表108-9を参照)のサブセットを使用できます。これらのオプションの詳細は、第110章「TopLinkの式の概要」を参照してください。
表108-8 式演算子でのインメモリー問合せのサポート
式演算子 | インメモリー問合せのサポート |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
脚注1 詳細は、108.7.1.5項「結合読取りとオブジェクト・レベルの読取り問合せ」を参照してください。
インメモリー問合せはいくつかの原因で失敗します。最も一般的な原因として次のことがあげられます。
問合せ式が複雑すぎてメモリー内で実行できない場合。
インダイレクション(遅延ロード)が使用されている未トリガーのValueHolderがある場合。インダイレクションを使用するオブジェクト・モデルはすべて、関連オブジェクトに一致する前に、ValueHolderをトリガーする必要があります。
TopLinkは、インダイレクション例外を処理するためのメカニズムを提供します。アプリケーションでのインダイレクション例外の処理方法を指定するには、次のInMemoryQueryIndirectionPolicy
メソッドを使用します。
throwIndirectionException
: デフォルト設定です。インダイレクション例外をスローする唯一の設定です。
triggerIndirection
: ValueHolderをすべてトリガーして問題を解消します。
ignoreIndirectionExceptionReturnConformed
: 未トリガーのValueHolderが検出された場合に、一致された結果を返します。つまり、データベースから一致する結果が返される必要があり、対象となる属性が変更されていないことを示す未トリガーのValueHolderが取得されるようにする必要がある場合に、このオプションを選択します。
ignoreIndirectionExceptionReturnNotConformed
: 未トリガーのValueHolderが検出された場合に、非一致な結果を返します。
注意: 新規アプリケーションを作成する際には、一致例外をすべてスローすることを検討してください。そうすることで、インメモリー問合せの失敗に関して、より詳しいフィードバックが得られます。詳細は、115.16.4.2項「一致するときの例外処理」を参照してください。 |
問合せでシングル・オブジェクトが主キーによって検索される場合、TopLinkでは、問合せから主キーを抽出し、データベースにアクセスせずにキャッシュからオブジェクトを返そうとします。オブジェクトがキャッシュ内に存在しない場合は、問合せはデータベースに対して実行され、結果のオブジェクトが作成されて、アイデンティティ・マップに配置されます。
問合せが主キー以外の選択基準に基づいている場合やすべて読取り問合せの場合、その問合せはデータベースに対して実行されます(ReadObjectQuery
またはReadAllQuery
のメソッドcheckCacheOnly
を使用していない場合)。問合せでは、結果セットの主キーがキャッシュ内のオブジェクトと照合され、キャッシュされたオブジェクトがあれば、結果セットに入れて返されます。
オブジェクトがキャッシュ内に存在しない場合、オブジェクトが作成されます。問合せがリフレッシュ問合せの場合は、すべてのオブジェクトの内容が問合せの結果セットで更新されます。アイデンティティ・マップを正しく構成して使用する場合は、オブジェクト・アイデンティティに対してequalsを使用します。
クライアントは、ある時点でデータが最新の状態になるように、オブジェクトをいつでもリフレッシュできます。
複合主キーを使用したリレーションシップの走査
複合主キーを使用してリレーションシップを走査し、オブジェクトを取得する場合、問合せキーを作成して使用する必要があります(110.4項「問合せキーと問合せ式」を参照)。複合主キーを含むクラスのマップされた属性ごとに問合せキーを追加することにより、TopLinkでキャッシュの主キーを使用できます。
2つの属性(A
およびB
)を含むMyClass
というクラスについて検討してみます。A
とB
は、両方とも1対1マッピングとしてデータベースにマップされており、主キーとして指定されています。
この場合、属性ごとに問合せキー(MyQueryKeyA
およびMyQueryKeyB
など)を作成し、他のクラスを経由せずにMyClassの主キーの属性をマップする必要があります。これで、この問合せキーを使用してキャッシュ内のオブジェクトを検索し、次のようにオブジェクトの主キーを問い合せることができます。
builder.get("MyQueryKeyA").equal(new Long("123456"));
通常は読取り問合せによって実行されるアイデンティティ・マップ・キャッシュの更新を無効にするには、dontMaintainCache
メソッドをコールします。これによって、後でアプリケーションで必要とされないオブジェクトを読み取る際に、問合せのパフォーマンスが向上し、部分オブジェクト問合せ中に例外を回避できます(109.2.1.2項「部分オブジェクト問合せを使用したオブジェクトの読取り」を参照)。
例108-1は、コードがデータベースからEmployee
オブジェクトを読み取り、その情報をファイルに書き込む方法を示します。
例108-1 アイデンティティ・マップ・キャッシュの更新の無効化
// Reads objects from the employee table and writes them to an employee file void writeEmployeeTableToFile(String filename, Session session) { Vector employeeObjects; // Create ReadAllQuery and set Employee as its reference class ReadAllQuery query = new ReadAllQuery(Employee.class); ExpressionBuilder builder = query.getExpressionBuilder(); query.setSelectionCriteria(builder.get("id").greaterThan(100)); query.dontMaintainCache(); Vector employees = (Vector) session.executeQuery(query); // Write all the employee data to a file Employee.writeToFile(filename, employees); }
キャッシュ内のオブジェクトをリフレッシュすることで、オブジェクトをデータベースに対して最新の状態に保つとともに、オブジェクト・アイデンティティを維持することができます。この項では、問合せAPIを使用して次のことを実行する方法について説明します。
ディスクリプタ・レベルでの問合せのリフレッシュを構成し(119.9項「キャッシュ・リフレッシュ機能の構成」を参照)、特定のオブジェクト・タイプのすべての問合せに対してキャッシュ・リフレッシュを適用します。キャッシュ・リフレッシュ・オプションを構成する前に、パフォーマンスへの影響を検討してください(12.10項「キャッシュの最適化」を参照)。
データベースのデータを使用してキャッシュ内のオブジェクトをリフレッシュするには、Session
のメソッドrefreshObject
またはReadObjectQuery
のメソッドsetShouldRefreshIdentityMapResult(true)
をコールします。
オブジェクトとその関連オブジェクトがリフレッシュによって更新される深さを制御できます。次の3つのオプションがあります。
CascadePrivateParts
: デフォルトのリフレッシュ動作。ローカル・レベルのオブジェクトと、プライベートに所有されたリレーションシップで参照されるオブジェクトをリフレッシュします。
CascadeNone
: オブジェクトの最初のレベルのみをリフレッシュします。関連オブジェクトはリフレッシュしません。
CascadeAll
: オブジェクト・ツリー全体をリフレッシュし、リーフ・オブジェクトに達したときに停止します。
CascadeMapping
: カスケード・リフレッシュするように構成されている各マッピングをリフレッシュします。
アイデンティティ・マップを問合せの結果で強制的にリフレッシュするには、次の例に示すように、refreshIdentityMapResult
メソッドを問合せに含めます。
例108-2 読取り問合せ中にアイデンティティ・マップ・キャッシュ内の問合せ結果をリフレッシュ
// Create ReadObjectQuery and set Employee as its reference class
ReadObjectQuery query = new ReadObjectQuery(Employee.class);
ExpressionBuilder builder = query.getExpressionBuilder();
query.setSelectionCriteria(builder.get("lastName").equal("Smith"));
query.refreshIdentityMapResult();
Employee employee = (Employee) session.executeQuery(query);
refreshIdentityMapResult
メソッドは、オブジェクトの属性をリフレッシュしますが、私有部分の属性はリフレッシュしません。ただし、ほとんどの状況では、オブジェクトの私有部分とその他の関連オブジェクトをリフレッシュして、データベースとの整合性を維持してください。
プライベートに所有された部分や関連部分をリフレッシュするには、次のメソッドを使用します。
cascadePrivateParts
: 私有オブジェクトをすべてリフレッシュします。
cascadeAllParts
: 関連オブジェクトをすべてリフレッシュします。
例108-3 cascadePrivatePartsメソッドの使用
ReadAllQuery query = new ReadAllQuery(Employee.class); query.refreshIdentityMapResult(); query.cascadePrivateParts(); Vector employees = (Vector) session.executeQuery(query);
注意: オブジェクトがセッション・キャッシュ内に存在する場合、refreshObject メソッドを使用して、オブジェクトとその私有部分をリフレッシュすることもできます。 |
デフォルトでは、問合せ結果はセッション・キャッシュに格納されるため、データベースにアクセスせずに問合せを繰り返し実行することが可能になります。これは、静的データに対して問合せを実行する際に便利です。
探しているオブジェクトの数は認識されていないため、デフォルトでは、すべて読取り問合せは常にデータベースに送信されます。ただし、オブジェクトがすでにキャッシュ内に存在する場合は、行から新規オブジェクトを作成する必要がないため、時間の節約になります。
詳細は、第102章「キャッシュの概要」を参照してください。
TopLinkでは、オブジェクト・キャッシュの他に、問合せキャッシュもサポートしています。この2つの間には次の違いがあります。
オブジェクト・キャッシュでは、主キーによってオブジェクトに索引付けし、主キー問合せでキャッシュ・ヒットを取得できるようにします。オブジェクトがすでに存在する場合、オブジェクト・キャッシュの使用により、データ・ソースにアクセスする問合せでは、オブジェクトおよびそれらのリレーションシップを作成する負荷を回避できます。
問合せキャッシュは、オブジェクト・キャッシュとは異なります。問合せキャッシュは、オブジェクトの主キーではなく問合せおよび問合せパラメータによって索引付けされます。これにより、同じパラメータを使用して実行されたすべての問合せが、問合せキャッシュ・ヒットを取得し、同じ結果セットを返すことができます。
デフォルトでは、ReadQuery
は、その問合せ結果セットをキャッシュしません。ただし、結果セットをキャッシュするように問合せを構成することはできます。これは、結果セットが変わることがまれにしかない問合せを頻繁に実行する際に便利です。問合せキャッシュでは、結果セットに対するハード参照は常に維持されます。異なるパラメータに対する、問合せキャッシュに保存される結果セットの数を構成することは、可能です。問合せキャッシュは、異なるパラメータを使用して最近実行した各問合せのサイズ値を維持します。
詳細は、111.13.1項「ReadQueryでの結果のキャッシュ方法」を参照してください。
キャッシュの無効化ポリシーを問合せの内部キャッシュに適用できます(111.13.2項「問合せレベルにおけるキャッシュの有効期限の構成方法」を参照)。詳細は、102.2.5項「キャッシュの無効化」を参照してください。
TopLinkでは、カーソルでの問合せキャッシュの使用をサポートしません。カーソルで問合せキャッシュを使用すると、例外がスローされます。カーソルの問合せの結果の詳細は、108.5.3項「ストリームとカーソルの問合せの結果」および111.11項「カーソルとストリームの問合せ結果の処理」を参照してください。
TopLinkでは、EJBファインダが取得するEnterprise Beanをキャッシュします。アプリケーションに対し、EJBファインダの結果のキャッシュを様々な方法で構成できます。また、キャッシュのリフレッシュを強制したり、キャッシュを無効化することができます。
この項の内容は次のとおりです。
基礎となる問合せに各種構成を適用して、アプリケーションにとって正しいキャッシュ動作を実現することができます。問合せのキャッシュ・オプションを制御するには、いくつかの方法があります。ほとんどの問合せでは、Oracle JDeveloperまたはTopLink Workbenchを使用してキャッシュ・オプションを設定できます。
キャッシュ・オプションはファインダ単位で設定できます。表108-10は、有効な値を示します。
表108-10 ファインダのキャッシュ・オプション
設定 | ファインダの動作 | 検索に使用されるファインダの動作 |
---|---|---|
|
セッション・キャッシュまたはデータベースに対して問合せを行う前に、作業ユニットのキャッシュをチェックします。ファインダの結果は必ず、未コミットの新規オブジェクト、削除されたオブジェクト、および変更されたオブジェクトに一致します。 |
単一のBeanまたはコレクションを返します。 |
|
TopLinkの内部キャッシュをバイパスして、データベースに対して問合せを行います。 |
単一のBeanまたはコレクションを返します。 |
|
オブジェクトのセッション・キャッシュをチェックします。 |
主キーのみを含み、単一のBeanを返します。 |
|
オブジェクトのセッション・キャッシュをチェックします。 |
主キーを含み(その他の検索パラメータを含む場合もあります)、単一のBeanを返します。 |
|
データベースにアクセスする前に、セッション・キャッシュで検索を行います。 |
単一のBeanを返します。 |
|
親セッション・キャッシュのみを検索し(作業ユニットのキャッシュは検索しない)、データベースは検索しません。 |
単一のBeanまたはコレクションを返します。 |
脚注1 デフォルトです。
TopLink問合せとTopLinkの作業ユニット、およびJTSへの作業ユニットの統合方法の詳細は、第113章「TopLinkトランザクションの概要」を参照してください。
注意: 手動で作成した問合せ(findOneByQuery 、findManyByQuery )によってファインダにキャッシュ・オプションを適用するには、TopLink APIを使用します。 |
デフォルトでは、返されたオブジェクトはすべてセッション・キャッシュに追加されます。ただし、返されるオブジェクトが非常に大きいとわかっている場合に、そのオブジェクトを格納する負荷を回避するには、この動作を無効にします。デフォルト構成をオーバーライドするには、dontMaintainCache
メソッドを問合せに実装するか、Oracle JDeveloperまたはTopLink Workbenchで、返されたオブジェクトのキャッシュを問合せに対して無効にします。
ファインダは、主キーがすでにキャッシュ内にあるオブジェクトの情報を、データベースから返すことができます。Oracle JDeveloperおよびTopLink Workbenchでキャッシュ・リフレッシュ・オプションをTRUE
に設定すると、問合せにより、オブジェクトの主キー以外の属性が、返された情報でリフレッシュされます。この処理は、findByPrimaryKey
ファインダだけではなく、Beanのすべての式ファインダおよびSQLファインダでも行われます。
問合せをJavaコードで作成する場合、refreshIdentityMapResult
メソッドを含めることで、このオプションを設定できます。このメソッドは、変更をBeanのプライベートに所有された部分に自動的にカスケードします。異なる動作が必要な場合は、動的ファインダを使用して問合せを構成します。
注意: このオプションをトランザクション内から起動すると、リフレッシュ処理により、オブジェクトの属性(まだデータベースに書き込まれていないものも含む)が上書きされます。 |
アプリケーションにOptimisticLock
フィールドが含まれている場合、キャッシュ・リフレッシュ・オプションをonlyRefreshCacheIfNewerVersion
オプションと併用します。そうすることで、データベース内のオブジェクトのバージョンがキャッシュ内のバージョンよりも新しい場合にのみ、キャッシュ内のオブジェクトがリフレッシュされます。
キャッシュ・リフレッシュ設定を持たないファインダの場合、onlyRefreshCacheIfNewerVersion
メソッドは効果がありません。