この章では、Oracle TopLink GridでOracle Coherenceを使用してJava Persistence API (JPA)アプリケーションをスケール・アウトできるようにする方法について説明します。TopLink Gridは、Coherenceを分散共有(L2)キャッシュとして使用することから、JP QL問合せをCoherenceに送ってグリッド全体でパラレル実行してデータベース負荷を削減することまで、スケール・アウトに関する多数のオプションをアプリケーションに提供します。TopLink Gridでは、スケール・アウトするアプリケーションをリライトする必要はありません。JPAへの投資を使用したまま、Coherenceのスケーラビリティを利用できます。
この章では、次の内容を説明します。
Oracle TopLink Gridは、EclipseLink JPAとCoherenceとの統合を可能にするOracle TopLinkの機能です。標準のJPAアプリケーションは、プライマリ・データ・ストア(一般的にリレーショナル・データベース)と直接対話します。ただし、TopLink Gridの場合、ドメイン・モデルの一部またはすべてをCoherenceデータ・グリッドに格納できます。この構成は、「グリッド基盤のJPA」とも呼ばれています。
TopLink Gridを簡単に構成して、Coherenceのプライマリ・データ・ストアとしての使用、グリッドに対する問合せの実行、およびCoherenceによる新規データと変更データにおける永続性の管理ができます。Coherenceでは、JPAとデータ・ストア間のレイヤーが提供されており、すべてのアプリケーション・インスタンスからデータベース・コールを直接オフロードできます。これにより、クラスタ化されたアプリケーションのデプロイメントでは、通常のデータベース操作の限界を超えるスケーラビリティが得られます
Oracle Technology NetworkのOracle TopLink Gridページには、TopLink Gridに対するCoherenceの追加情報とコード例があります。
http://www.oracle.com/technetwork/middleware/ias/tl-grid-097210.html
これらはアプリケーションで使用できる典型的なグリッド基盤のJPA構成です。
グリッド・キャッシュ構成。CoherenceをTopLink L2(共有)キャッシュとして使用します。この構成では、Coherenceのキャッシュにすべて事前ロードできずデータベースでホストされるデータに依存するJPAアプリケーションにCoherenceのデータ・グリッドを適用します。事前ロードができない理由には、Coherenceのフィルタの機能セットを超える非常に複雑な問合せ、古いキャッシュの原因となるサード・パーティ製データベースによる更新、ネイティブSQL問合せ、ストアド・プロシージャやトリガーへの依存などがあります。
この構成では、ローカルL2キャッシュを調整することなく、TopLinkを大規模なクラスタにスケール・アップできます。エンティティに対する更新は、トランザクションがコミットされると即時にすべてのCoherenceクラスタ・メンバーで使用可能になります。詳細は、「グリッド・キャッシュ構成」を参照してください。
グリッド読取り構成。この構成は、(比較的安定した)大容量データへ高速にアクセスして変更をデータベースへ同期的に書き込む必要のあるエンティティに最適です。これらのエンティティでは、Coherenceキャッシュへの移入にキャッシュ・ウォーミングが使用されますが、各問合せは必要に応じてデータベースに送信することもできます。詳細は、「グリッド読取り構成」を参照してください。
グリッド・エンティティ構成。この構成は、(比較的安定した)大容量データへ高速にアクセスする必要があり、更新が比較的少ないアプリケーションに最適です。ライトビハインドを使用してこの構成をCoherenceキャッシュ・ストアと組み合せると、データベース更新を非同期に実行することにより、アプリケーションのレスポンス時間を向上させることができます。詳細は、「グリッド・エンティティ構成」を参照してください。
TopLink Gridには次のような利点があります。
標準JPAに合せた注釈またはXML構成を使用した単純なアプリケーション構成。
複雑なオブジェクト・グラフと関係をCoherenceに格納する機能。
グリッドに格納するエンティティとバッキング・データベースに直接格納するエンティティを選択する機能。
グリッド内のJP QL問合せを実行またはデータベースに対して直接実行できます。
即時関係と遅延関係の両方でエンティティをCoherenceに格納できます。
TopLink GridはEclipseLink JPA実装(EclipseLink)とOracle Coherenceとを統合するもので、これらの開発アプローチを提供します。
JPAを使用してアプリケーションを構築し、データ・グリッドの機能を透過的に使用してスケーラビリティとパフォーマンスを向上させることができます。このようなグリッド基盤のJPAアプローチでは、TopLink Gridが、キャッシュのセットと、EclipseLink JPAでのCoherenceの使用方法を制御できる問合せ構成オプションを提供します。これらの実装は、oracle.eclipselink.coherence.integratedパッケージ内にあります。詳細は、「グリッド基盤のJPA構成」を参照してください。
既存のNative ORMアプリケーションがある場合、それらとともにEclipseLink Native Object Relational Mapping (ORM)フレームワークを使用できます。Native ORMアプローチは、グリッド基盤のJPAと非常によく似ていますが、キャッシュの使用方法を構成するために注釈を使用しません。かわりに、このアプローチは、適切なキャッシュ動作を定義する修正メソッドを採用します。詳細は、「EclipseLink Native ORMの構成」を参照してください。
Coherence APIをTopLink Gridによって支援されたキャッシュとともに使用して、JPAに対して実装された特殊なキャッシュ・ローダーおよびキャッシュ・ストア・インタフェースでリレーショナル・データにアクセスできます。
この従来のCoherenceアプローチでは、TopLink GridはEclipseLink JPA用に最適化されたoracle.eclipselink.coherence.standaloneパッケージにCacheLoaderおよびCacheStore実装を提供します。この手法については、「TopLink GridとCoherenceクライアント・アプリケーションの使用」を参照してください。
JPAアプリケーションをCoherenceのデータ・グリッドと統合する際は、可能性のあるメリットと制限事項に注意してください。あらゆる可能性を理解するためには、グリッドの動作およびグリッドとJPA構成との関連性について理解する必要があります。
TopLink Gridを使用するための必須ファイルは、javax.persistence_2.0.0.0_2-0.jar、eclipselink.jarおよびtoplink-grid.jarです。Coherenceの標準インストールを実行した場合、これらのファイルは次の場所に格納されます。
.../Oracle_Home/oracle_common/modules/javax.persistence_2.0.0.0_2-0.jar
.../Oracle_Home/oracle_common/modules/oracle.toplink12.1.2/eclipselink.jar
.../Oracle_Home/oracle_common/modules/oracle.toplink12.1.2/toplink-grid.jar
この項では、グリッド基盤のJPAと、グリッド・キャッシュ構成、グリッド読取り構成およびグリッド・エンティティ構成でのオブジェクトの読取りおよび書込み方法について説明します。また、これらの構成でCoherenceキャッシュに対して問合せを実行する方法についても説明します。
この項の内容は次のとおりです。
グリッド基盤のJPAという表現は、JPAとデータ・グリッドの機能を使用してスケーラビリティとパフォーマンスが向上したアプリケーションを構築することを意味します。グリッド基盤のJPAアプローチでは、TopLink Gridによって、キャッシュのセットと、EclipseLink JPAでのCoherenceの使用方法を制御できる問合せ構成オプションが提供されます。
Coherenceを分散共有(L2)キャッシュとして構成することも、Coherenceをプライマリ・データ・ストアとして使用することもできます。また、データベースのかわりにCoherenceデータ・グリッド内で問合せを実行するようエンティティを構成することもできます。こうすると、クラスタ化されたアプリケーション・デプロイメントを、データベースがボトルネックとなるような操作を越えて拡張できます。
図1-1に、アプリケーション、TopLink、Coherenceおよびデータベース間の関係を示します。
グリッド基盤のJPA構成で使用されるAPIは、toplink-grid.jarファイルに含まれています。表1-1に、グリッド基盤のJPA構成で使用されるoracle.eclipselink.coherence.integratedパッケージの主要クラスの一部をリストします。
表1-1 グリッド基盤のJPAアプリケーションを構築するためのTopLink Gridクラス
| クラス名 | 説明 |
|---|---|
|
|
Coherence |
|
|
Coherence |
|
|
Coherence読取り構成を有効にします。 |
|
|
Coherence読取り/書込み構成を有効にします。 |
|
|
キャッシュ・インスタンスを内部EclipseLink共有キャッシュのかわりにCoherenceにキャッシュできるようにします。内部TopLink L2キャッシュに対するすべてのコールは、Coherenceにリダイレクトされます。 |
|
|
問合せがCoherenceキャッシュをバイパスし、データベースに直接送信されるようにします。 |
構成では、標準JPAランタイム構成ファイルpersistence.xmlおよびJPAマッピング・ファイルorm.xmlも使用されます。Coherenceキャッシュ構成ファイルcoherence-cache-config.xmlを使用してデフォルトのCoherence設定をオーバーライドし、キャッシュ・ストア・キャッシュ・スキームを定義する必要もあります。
グリッド・キャッシュ構成は、TopLink Gridの基本構成とみなすことができます。この構成では、CoherenceがTopLink共有(L2)キャッシュとして機能します。これにより、Coherenceのキャッシュにすべて事前ロードできずデータベースでホストされるデータに依存するJPAアプリケーションに対してCoherenceのデータ・グリッドを適用できます。データを事前ロードできない理由には、Coherenceのフィルタの機能を超える非常に複雑な問合せ、サード・パーティ製データベースの更新による古いキャッシュ、およびネイティブSQL問合せ、ストアド・プロシージャ、トリガーへの依存などがあります。
CoherenceをTopLink Gridキャッシュとして使用すると、ローカル共有キャッシュを調整しなくても、TopLinkを大規模なクラスタにスケール・アップできます。エンティティに対する更新は、トランザクションがコミットされると即時にすべてのCoherenceクラスタ・メンバーで使用可能になります。
一般に、グリッド・キャッシュ構成の読取りおよび書込み操作には次の特徴があります。
主キー問合せでは、最初にCoherenceキャッシュからのエンティティの取得が試行されます。この試行に失敗すると、データベースが問合せされ、Coherenceキャッシュが問合せ結果で更新されます。次の「グリッド・キャッシュ構成でのオブジェクトの読取り」を参照してください。
非主キー問合せがデータベースに対して実行され、結果がCoherenceキャッシュに照らしてチェックされます。これによって、すでにキャッシュされているエンティティの構築によるパフォーマンスへの悪影響が回避されます。新しく問合せされたエンティティがCoherenceキャッシュに挿入されます。
書込み操作では、データベースが更新され、コミットに成功した場合は更新されたエンティティがCoherenceキャッシュに挿入されます。「グリッド・キャッシュ構成でのオブジェクトの書込み」を参照してください。
詳細な例については、「グリッド・キャッシュ構成の例」を参照してください。
Coherenceをエンティティの分散キャッシュとして使用するには、EclipseLinkで共有キャッシュを有効にする必要があります。共有キャッシュはすべてのエンティティに対してデフォルトで有効になっていますが、persistence.xmlファイルでeclipselink.cache.shared.defaultプロパティを設定することにより、デフォルトを明示的にtrueまたはfalseに設定できます。特定のエンティティでデフォルトをオーバーライドするには、@Cache注釈を使用するか、eclipselink-orm.xmlファイルで対応するXML <cache>要素を指定します。詳細は、次を参照してください:
http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_(ELUG)#How_to_Use_the_.40Cache_Annotation
グリッド・キャッシュ構成では、最初にCoherenceキャッシュに送られる主キー問合せを除くすべての読取り問合せがデータベースに送られます。キャッシュ・ミスがあった場合は、データベース問合せが実行されます。
データベースから問合せされたすべてのエンティティはCoherenceキャッシュに挿入されます。これにより、エンティティはすべてのクラスタ・メンバーに対して即時に使用可能になります。TopLinkはデフォルトで、データベース結果からの新しいエンティティの構成を回避するためにキャッシュを利用するため、この動作が非常に有効になります。
TopLinkは、問合せの結果返された行ごとに、結果の行の主キーを使用して、キャッシュから対応するエンティティを問い合せます。キャッシュにエンティティが含まれていれば、そのエンティティが使用され、新しいエンティティは構築されません。このアプローチではオブジェクトのビルドに関連するコストを排除することで問合せのコストを削減できるため、特にウォーム・キャッシュを使用する場合は、アプリケーションのパフォーマンスが大幅に向上する可能性があります。
図1-2に、グリッド・キャッシュ構成での読取り問合せのパスを示します。
アプリケーションがfind問合せを発行します。
主キー問合せでは、TopLinkは最初にCoherenceキャッシュを問い合せます。
オブジェクトがCoherenceキャッシュに存在しない場合、TopLinkはデータベースを問い合せます。
主キー問合せを除くすべての読取り問合せでは、TopLinkは最初にデータベースを問い合せます。
読み取られたオブジェクトは、Coherenceキャッシュに挿入されます。
グリッド・キャッシュ構成では、TopLinkがすべてのデータベース書込み操作(挿入、更新、削除)を実行します。その後、Coherenceキャッシュがデータベースへの変更を反映するように更新されます。TopLinkには、大量のデータを書き込む際のパフォーマンス機能が数多く用意されています(バッチ書込み、パラメータ・バインディング、ストアド・プロシージャ・サポート、データベース制約を満たすための文の順序付けなど)。
図1-3に、グリッド・キャッシュ構成でのオブジェクトの書込みと永続化のパスを示します。
アプリケーションがcommit問合せを発行します。
TopLinkがデータベースを更新します。
トランザクションが正常に完了すると、TopLinkはCoherenceキャッシュを更新します。
これらの例のコードは、次のURLで入手できます。
http://www.oracle.com/technetwork/middleware/toplink/examples-325517-en-ca.html
例1-1のキャッシュ構成ファイル(coherence-cache-config.xml)は、キャッシュを定義し、ラッパー・シリアライザを構成して関係のシリアライズをサポートします。
例1-1 グリッド・キャッシュ構成のキャッシュの構成
<cache-config>
<caching-scheme-mapping>
<cache-mapping>
<cache-name>*</cache-name>
<scheme-name>eclipselink-distributed</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<distributed-scheme>
<scheme-name>eclipselink-distributed</scheme-name>
<service-name>EclipseLinkJPA</service-name>
<!--
Configure a wrapper serializer to support serialization of relationships.
-->
<serializer>
<class-name>oracle.eclipselink.coherence.integrated.cache.WrapperSerializer</class-name>
</serializer>
<backing-map-scheme>
<!--
Backing map scheme with no eviction policy.
-->
<local-scheme>
<scheme-name>unlimited-backing-map</scheme-name>
</local-scheme>
</backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
</caching-schemes></cache-config>
グリッド・キャッシュを使用するようにエンティティを構成するには、例1-2に示すように@Customizer注釈とGridCacheCustomizerクラスを使用します。このクラスは、内部のTopLink GridキャッシュへのすべてのTopLinkコールをインターセプトし、それらをCoherenceキャッシュにリダイレクトします。
例1-3では、TopLinkは挿入を実行して新しい従業員を作成しています。エンティティはEntityManagerを通じて永続化され、データベースに配置されます。トランザクションに成功すると、Coherenceキャッシュが更新されます。
例1-3 グリッド・キャッシュ構成のオブジェクトの挿入
EntityManagerFactory emf = Persistence.createEntityManagerFactory("employee-pu");// Create an employee with an address and telephone number.EntityManager em = emf.createEntityManager();em.getTransaction().begin();Employee employee = createEmployee();em.persist(employee);em.getTransaction().commit(); em.close();
例1-4では、指定されたJPQL問合せがデータベースに送られます。問合せ結果はCoherenceキャッシュに照らして解決され、以前にキャッシュされたオブジェクトをビルドするコストが回避されます。
例1-4 グリッド・キャッシュ構成のオブジェクトの問合せ
EntityManagerFactory emf = Persistence.createEntityManagerFactory("employee-pu");EntityManager em = emf.createEntityManager();List<Employee> employees =em.createQuery("select e from Employee e where e.lastName = :lastName").setParameter("lastName", "Smith").getResultList();for (Employee employee : employees) { System.err.println(employee); for (PhoneNumber phone : employee.getPhoneNumbers()) { System.err.println("\t" + phone); } } emf.close();
グリッド読取り構成は、(比較的安定した)大容量のデータに高速にアクセスする必要があり、変更をデータベースに同期的に書き込む必要のあるエンティティに対して使用します。これらのエンティティでは、通常はCoherenceキャッシュへの移入にキャッシュ・ウォーミングが使用されますが、必要に応じて個々の問合せをデータベースに送ることもできます。
一般に、グリッド読取り構成の読取りおよび書込み操作には次の特徴があります。
読取り操作では、Coherenceキャッシュからオブジェクトが取得されます。キャッシュ・ローダーの構成は、JPQL問合せに影響しません。次の「グリッド読取り構成でのオブジェクトの読取り」を参照してください。
書込み操作によりデータベースが更新され、コミットが正常に完了すると、更新されたエンティティがCoherenceキャッシュに挿入されます。「グリッド読取り構成でのオブジェクトの書込み」を参照してください。
詳細な例については、「グリッド読取り構成の例」を参照してください。
グリッド読取り構成では、すべての主キーおよび非主キー問合せがCoherenceキャッシュに送られます。TopLink Gridでは、問合せの処理時間を短縮するために、データ・グリッド全体での問合せのパラレル処理をサポートしています。Coherenceには、オブジェクト形式のデータがすでに含まれており、データベースとの通信やオブジェクト構築で発生するパフォーマンスへの影響を回避します。
グリッド読取り構成を使用する場合、find(...)メソッドによってリクエストされたエンティティがCoherence内に存在しなければ、nullが返されます。ただし、そのエンティティのキャッシュに対してキャッシュ・ローダーが構成されていれば、Coherenceはデータベースからオブジェクトをロードしようとします。これは、主キー問合せにのみ該当します。
キャッシュ・ローダーを構成しても、Coherenceフィルタに変換されるJPQL問合せに影響を与えることはありません。Coherenceはフィルタを使用して検索する際に、キャッシュ内のエンティティ・セットに対してのみ操作を実行するため、データベースは問合せされません。ただし、次の例に示すように、oracle.eclipselink.coherence.integrated.querying.IgnoreDefaultRedirectorクラスを使用して、問合せごとに問合せをCoherenceではなくデータベースに送ることも可能です。
query.setHint(QueryHints.QUERY_REDIRECTOR, new IgnoreDefaultRedirector());
データベース問合せで取得されたオブジェクトはすべて、以降の問合せで使用できるようCoherenceキャッシュに追加されます。この構成はデフォルトで、Coherenceを介してエンティティに対するすべての問合せを解決するため、Coherenceのキャッシュをすべての問合せ対象のデータでウォーミングする必要があります。
グリッド読取り構成では、単一のエンティティ・タイプからデータを抽出する予測問合せ(レポート)もCoherenceに送られます。たとえば、次のJPQL問合せは、Coherenceキャッシュに含まれるすべての従業員の姓名を返します。
select e.firstName, e.lastName from Employee e
このタイプの問合せは、ユーザー・インタフェースにドロップダウン・リストを移入するときなど、エンティティ全体が必要ではない場合に役立ちます。
EclipseLink JPAはすべてのデータベース更新を実行してから更新されたオブジェクトをCoherenceに伝播するため、キャッシュ・ストアはグリッド読取り構成と互換性がありません。キャッシュ・ストアを使用する場合、Coherenceはオブジェクトの書込みを再試行します。
EclipseLink JPA問合せのヒントの使用に関する完全な情報は、『Oracle Fusion Middleware Oracle TopLink Java Persistence API (JPA)拡張リファレンス』のJPA問合せカスタマイズの拡張に関する項、および『Oracle Fusion Middleware Oracle TopLinkの理解』のJPA問合せのヒントに関する項を参照してください。
図1-4に、グリッド読取り構成での問合せのパスを示します。
アプリケーションがJPQL問合せを発行します。
TopLinkはCoherenceキャッシュに対してフィルタを実行します。
TopLinkはCoherenceキャッシュからの結果のみを返します。データベースは問合せされません。
グリッド読取り構成では、TopLinkがすべてのデータベース書込み操作(挿入、更新、削除)を直接実行します。その後、Coherenceキャッシュがデータベースへの変更を反映するように更新されます。TopLinkには、大量のデータを書き込む際のパフォーマンス機能が数多く用意されています。これらには、バッチ書込み、パラメータ・バインディング、ストアド・プロシージャ・サポート、データベース制約を満たすための文の順序付けなどがあります。
このアプローチは、長所を最大限に生かすことができます。1つはデータベースの更新が効率的に行われること、そしてもう1つはCoherenceのデータ・グリッド全体に対して問合せをパラレルに実行できることで、さらに個々の問合せをデータベースに直接送ることもできます。
図1-5に、グリッド読取り構成でのオブジェクトの書込みと永続化のパスを示します。
アプリケーションがcommit問合せを発行します。
TopLinkがデータベースを更新します。
トランザクションが正常に完了すると、TopLinkはCoherenceキャッシュを更新します。
これらの例のコードは、次のURLで入手できます。
http://www.oracle.com/technetwork/middleware/toplink/examples-325517-en-ca.html
例1-5のキャッシュ構成ファイル(coherence-cache-config.xml)は、キャッシュを定義し、ラッパー・シリアライザを構成して関係のシリアライズをサポートします。oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheLoaderクラスは、キャッシュ・ストア・スキームを定義します。
例1-5 グリッド読取り構成のキャッシュの構成
<cache-config>
<caching-scheme-mapping>
<cache-mapping>
<cache-name>*</cache-name>
<scheme-name>eclipselink-distributed-readonly</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<distributed-scheme>
<scheme-name>eclipselink-distributed-readonly</scheme-name>
<service-name>EclipseLinkJPAReadOnly</service-name>
<!--
Configure a wrapper serializer to support serialization of relationships.
-->
<serializer>
<class-name>oracle.eclipselink.coherence.integrated.cache.WrapperSerializer</class-name>
</serializer>
<backing-map-scheme>
<read-write-backing-map-scheme>
<internal-cache-scheme>
<local-scheme />
</internal-cache-scheme>
<!--
Define the cache scheme.
-->
<cachestore-scheme>
<class-scheme>
<class-name>oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheLoader</class-name>
<init-params>
<param-type>java.lang.String</param-type>
<param-value>{cache-name}</param-value>
</init-param>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>employee-pu</param-value>
</init-param>
</init-params>
</class-scheme>
</cachestore-scheme>
<read-only>true</readonly>
</read-write-backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
</caching-schemes></cache-config>
Coherenceキャッシュを読み取るようにエンティティを構成するには、例1-6に示すように@Customizer注釈とCoherenceReadCustomizerクラスを使用します。
例1-7では、TopLinkは挿入を実行して新しい従業員を作成しています。トランザクションが正常に完了すると、新しいオブジェクトがその主キーによってCoherenceキャッシュに挿入されます。
例1-7 グリッド読取り構成のオブジェクトの挿入
EntityManagerFactory emf = Persistence.createEntityManagerFactory("employee-pu");// Create an employee with an address and telephone number EntityManager em = emf.createEntityManager(); em.getTransaction().begin();Employee employee = createEmployee();em.persist(employee);em.getTransaction().commit(); em.close(); emf.close();
従業員を検索する際に、読取り問合せがCoherenceキャッシュに送られます。例1-8に示すように、JPQL問合せがCoherenceフィルタに変換されます。
例1-8 グリッド読取り構成のオブジェクトの問合せ
EntityManagerFactory emf = Persistence.createEntityManagerFactory("employee-pu");EntityManager em = emf.createEntityManager();List<Employee> employees =em.createQuery("select e from Employee e where e.lastName = :lastName").setParameter("lastName", "Smith").getResultList();for (Employee employee : employees) { System.err.println(employee); for (PhoneNumber phone : employee.getPhoneNumbers()) { System.err.println("\t" + phone); } }emf.close();
特定のID(キー)を使用してCoherenceキャッシュからオブジェクトを取得するには、em.find(Entity.class, ID)メソッドを使用します。指定したIDを持つオブジェクトがキャッシュに存在しない場合は、データベースを問い合せるようCoherenceキャッシュ・ローダーを構成して、オブジェクトを検出することもできます。
グリッド・エンティティ構成は、(比較的安定した)大容量のデータに高速にアクセスする必要があり、実行される更新が比較的少ないアプリケーションに対して使用してください。ライトビハインドを使用してこの構成をCoherenceキャッシュ・ストアと組み合せると、データベース更新を非同期に実行することにより、アプリケーションのレスポンス時間を向上させることができます。
一般に、グリッド・エンティティ構成の読取りおよび書込み操作には次の特徴があります。
読取り操作では、Coherenceキャッシュからオブジェクトが取得されます。「グリッド・エンティティ構成でのオブジェクトの読取り」を参照してください。
書込み操作により、オブジェクトがCoherenceキャッシュに挿入されます。キャッシュ・ストアが構成されている場合、TopLinkはデータベースに対する書込み操作も実行します。「グリッド・エンティティ構成でのオブジェクトの書込み」を参照してください。
詳細な例については、「グリッド・エンティティ構成の例」を参照してください。
グリッド・エンティティ構成でのオブジェクトの問合せは、グリッド読取り構成と同じです。詳細は、「グリッド・キャッシュ構成でのオブジェクトの読取り」を参照してください。
グリッド・エンティティ構成では、EntityManagerインスタンスを介して永続化、更新またはマージされたオブジェクトはすべて、適切なCoherenceキャッシュに挿入されます。Coherenceキャッシュ内のオブジェクトをデータベースに対して永続化するには、キャッシュごとにEclipseLink JPAキャッシュ・ストア(oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStore)を構成する必要があります。
ライトビハインドを使用して更新済のオブジェクトの一括書込みを非同期的に行うよう、キャッシュ・ストアを構成することもできます。詳細は、『Oracle Fusion Middleware Oracle Coherenceでのアプリケーションの開発』を参照してください。
図1-6に、グリッド・エンティティ構成でのオブジェクトの書込みと永続化のパスを示します。
アプリケーションがcommitコールを発行します。
TopLinkはすべての問合せを送って、Coherenceキャッシュを更新します。
Coherenceのキャッシュ・ストアを構成すると(オプション)、TopLinkはデータベースも更新します。
キャッシュ・ストアを使用する場合、Coherenceはすべての書込み操作が成功することを前提とするため、TopLinkに失敗を通知しません。このため、Coherenceキャッシュがデータベースの内容と異なることがあります。Coherenceとサード・パーティ製アプリケーションによってデータベースが同時に更新された場合に発生する可能性のあるデータの破損から保護するためにオプティミスティック・ロックを使用することはできません。
Coherenceキャッシュ・メンバーがデータベースに更新を書き込む順序は予測できないため、参照整合性は保証できません。参照整合性制約はデータベースから削除する必要があります。そうしないと、書込み操作が次のエラーで失敗することがあります。
org.eclipse.persistence.exceptions.DatabaseException Internal Exception: java.sql.BatchUpdateException: ORA-02292: integrity constraint violated - child record found Error Code: 2292
これらの例のコードは、次のURLで入手できます。
http://www.oracle.com/technetwork/middleware/toplink/examples-325517-en-ca.html
例1-9のキャッシュ構成ファイル(coherence-cache-config.xml)は、ラッパー・シリアライザを構成して関係のシリアライズをサポートします。oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStoreクラスは、キャッシュ・ストア・スキームを定義します。
例1-9 グリッド・エンティティ構成のキャッシュの構成
<cache-config>
<caching-scheme-mapping>
<cache-mapping>
<cache-name>*</cache-name>
<scheme-name>eclipselink-distributed-readwrite</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<distributed-scheme>
<scheme-name>eclipselink-distributed-readwrite</scheme-name>
<service-name>EclipseLinkJPAReadWrite</service-name>
<!--
Configure a wrapper serializer to support serialization of relationships.
-->
<serializer>
<class-name>oracle.eclipselink.coherence.integrated.cache.WrapperSerializer</class-name>
</serializer>
<backing-map-scheme>
<read-write-backing-map-scheme>
<internal-cache-scheme>
<local-scheme />
</internal-cache-scheme>
<!--
Define the cache scheme
-->
<cachestore-scheme>
<class-scheme>
<class-name>oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStore</class-name>
<init-params>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>{cache-name}</param-value>
</init-param>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>employee-pu</param-value>
</init-param>
</init-params>
</class-scheme>
</cachestore-scheme>
</read-write-backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
</caching-schemes>
</cache-config>
Coherenceを読み取るようにエンティティを構成するには、例1-10に示すように@Customizer注釈とCoherenceReadWriteCustomizerクラスを使用します。
例1-11では、TopLinkは挿入を実行して新しい従業員を作成しています。エンティティはEntityManagerインスタンスによって永続化され、適切なCoherenceキャッシュに挿入されます。
例1-11 グリッド・エンティティ構成のオブジェクトの永続化
EntityManagerFactory emf = Persistence.createEntityManagerFactory("employee-pu");// Create an employee with an address and telephone number. EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Employee employee = createEmployee();em.persist(employee);em.getTransaction().commit(); em.close();
例1-12に示すように、従業員を検索する際に、読取り問合せがCoherenceキャッシュに送られます。
例1-12 グリッド・エンティティ構成のオブジェクトの問合せ
EntityManagerFactory emf = Persistence.createEntityManagerFactory("employee-pu");EntityManager em = emf.createEntityManager();List<Employee> employees =em.createQuery("select e from Employee e where e.lastName = :lastName").setParameter("lastName", "Smith").getResultList();for (Employee employee : employees) { System.err.println(employee); for (PhoneNumber phone : employee.getPhoneNumbers()) { System.err.println("\t" + phone); } } emf.close();
特定のID(キー)を使用してCoherenceキャッシュからオブジェクトを取得するには、em.find(Entity.class, ID)メソッドを使用します。指定したIDを持つオブジェクトがキャッシュに存在しない場合は、データベースを問い合せるようCoherenceキャッシュ・ストアを構成して、オブジェクトを検出することもできます。
グリッド読取り構成とグリッド・エンティティ構成では、TopLink GridはJPQL問合せからCoherenceフィルタへの変換とグリッドでの問合せの実行を試行します。ただし、一部の問合せはフィルタに変換できません。TopLink Gridは、このような問合せを検出すると、データベースに自動的にフェイルオーバーして問合せを実行します。TopLinkでは、JPQLからフィルタへの変換に失敗した場合に呼び出されるユーザー定義の変換失敗委任オブジェクトを指定できます。変換失敗委任は、eclipselink.coherence.query.translation-failure-delegate永続性ユニット・プロパティを宣言することで構成します。たとえば、次のようにします。
<property name="eclipselink.coherence.query.translation-failure-delegate" value="org.example.ExceptionFailoverPolicy"/>
変換失敗委任では、translationFailed(DatabaseQuery query, Record arguments, Session session)という単一のメソッドを定義するoracle.eclipselink.coherence.integrated.querying.TranslationFailureDelegateクラスを実装する必要があります。
リレーションシップとともにエンティティをCoherenceキャッシュに格納するとき、TopLink Gridは、リレーションシップ情報を維持するラッパー・クラスを生成します。この方法で、オブジェクトが(eagerまたはlazyで)Coherenceキャッシュから読み取られるときにリレーションシップを解決できます。
Coherence APIを使用してエンティティをCoherenceキャッシュから直接読み取ると、ラッパーは自動的には削除されません。例1-13に示すように、シリアライザでsetNotEclipseLink(true)メソッドを呼び出すことによりプログラムで自動アンラップを構成できます。また、システム・プロパティをeclipselink.coherence.not-eclipselinkとして設定して、エンティティを自動的にアンラップすることもできます。
正しく構成されると、キャッシュget操作はアンラップされたエンティティを返します。
この項では、次のトピックについて説明します。
特定のID(キー)を使用してCoherenceキャッシュからエンティティを取得するには、em.find(Entity.class, ID)メソッドを使用します。たとえば、次のコードはキー8のエンティティをCoherence Employeeキャッシュから取得します。
em.find(Employee.class, 8)
エンティティがCoherenceキャッシュ内に見つからない場合、TopLinkはデータベースに対してSELECT文を実行します。結果が見つかると、エンティティが構成されてCoherenceに挿入されます。問合せ固有の動作は、Coherenceキャッシュ構成によって決まります。
グリッド・キャッシュ構成でfindメソッドを呼び出すと、キャッシュ・ミス時にデータベースに対してSELECT文が実行され、キャッシュが更新されます。
グリッド読取り構成またはグリッド・エンティティ構成でfindメソッドを呼び出すと、Coherenceキャッシュに対してget操作が実行されます。キャッシュ・ミスの場合は、CacheLoaderインスタンス(構成されている場合)を使用してデータベースに対してSELECT文が実行されます。
特定の選択基準と一致するエンティティを取得するには、em.createQuery("...")メソッドを使用します。問合せ固有の動作は、Coherenceキャッシュ構成によって決まります。
グリッド・キャッシュ構成では、問合せは常にデータベースに対してSELECT文を実行します。たとえば、次のコードはSELECT文を実行してJohnという名前の従業員を検索します。
em.createQuery("select e from Employee e where e.name='John'")
グリッド読取り構成とグリッド・エンティティ構成では、問合せはCoherenceキャッシュに対して実行されます。キャッシュに選択基準と一致するエンティティが存在しない場合は、何も返されません。これは、問合せを実行する前にキャッシュをウォーミングする必要のある理由の一例です。
キャッシュ・ストアとキャッシュ・ローダーでは、問合せは主キーに対してのみ実行されます。
索引を使用すると、値(またはそれらの値の属性)および対応するキーをキャッシュ内で関連付けて、問合せのパフォーマンスを向上させることができます。TopLink Gridでは、@Property注釈で索引を宣言できます。IntegrationPropertiesクラスはINDEXEDプロパティを提供します。
例1-14の@Property注釈は、name属性が索引付けされることを宣言しています。TopLink Gridは、Publisherキャッシュ内のその属性の索引を定義します。
例1-14 TopLink GridへのCoherence問合せ索引の公開
import static oracle.eclipselink.coherence.IntegrationProperties.INDEXED;import oracle.eclipselink.coherence.integrated.config.CoherenceReadCustomizer;@Customizer(CoherenceReadCustomizer.class)public class Publisher implements Serializable { ...@Property(name=INDEXED, value="true")private String name; ...
索引が付けられたら、次のようなJPQL問合せを発行して、キャッシュ内の名前がSで始まるすべてのPublishersを返すことができます。
SELECT Publisher p WHERE p.name like 'S%'
内部的には、Coherenceはグリッドに格納されているすべてのPublisherオブジェクトをデシリアライズして検証するかわりにname索引を調べて一致を探すことで問合せを処理します。デシリアライズを回避することで、問合せの実行時間が大幅に向上し、一時的にデシリアライズされたオブジェクトのガベージ・コレクションが不要になり、CPU使用量が削減されます。
Coherenceキャッシュの問合せには次の制約があります。
Coherenceのフィルタ・フレームワークは単一キャッシュに制限されているため、JPQLのjoin問合せをフィルタに変換することはできません。すべてのjoin問合せはデータベースに対して実行されます。
このリリースのTopLink Gridでは、JPQLバルク更新および削除をサポートしていません。
この項では、広範なオブジェクト・リレーショナル・マッピング・フレームワークであるEclipseLink Native Object Relational Mapping (ORM)について説明します。また、Oracle JDeveloperを使用した修正メソッドの構成方法と、EclipseLink Native ORMキャッシュ・ストアおよびキャッシュ・ローダーの構成方法についても説明します。
この項の内容は次のとおりです。
EclipseLink Native ORMは、広範なオブジェクト・リレーショナル・マッピング・フレームワークを提供します。XMLを使用して宣言により構成される様々な機能とともに、高パフォーマンスのオブジェクト永続化を提供します。これらの様々な機能には、キャッシング(クラスタリングされたキャッシングを含む)、高度なデータベース固有機能、およびパフォーマンス・チューニングと管理のオプションが含まれます。
グリッド基盤のJPA構成と同様に、EclipseLink ORMを採用するアプリケーションはCoherenceキャッシュにアクセスできます。ただし、グリッド基盤のJPA構成とは異なり、EclipseLink ORMアプリケーションはキャッシュの使用方法を構成するために@Customizer注釈を使用しません。かわりに、通常は適切なキャッシュ動作を定義する修正メソッドを呼び出します。
EclipseLink Native ORMで使用されるキャッシュ・ストアおよびキャッシュ・ローダーAPIは、toplink-grid.jarファイルに含まれています。表1-2で、EclipseLink Native ORMのAPIについて説明します。これらのクラスはoracle.eclipselink.coherence.integratedパッケージにあります。
表1-2 Native ORM構成用のEclipseLinkクラス
| クラス名 | 説明 |
|---|---|
|
|
ネイティブEclipseLink構成で使用する必要のあるCoherenceキャッシュ・ストア( |
|
|
ネイティブEclipseLink構成で使用する必要のあるCoherenceキャッシュ・ローダー( |
|
|
Coherence読取り構成を有効にします。 |
|
|
Coherence読取り/書込み構成を有効にします。 |
|
|
エンティティ・インスタンスを内部EclipseLink共有キャッシュのかわりにCoherenceにキャッシュできるようにします。 |
署名の2つ目の初期化パラメータsessionNameは、EclipseLink構成ファイルMETA-INF/sessions.xmlにリストされている必要のあるマッピング・プロジェクトの名前を表します。
EclipseLinkNativeCacheStoreクラスとEclipseLinkNativeCacheLoaderクラスでは、EclipseLink Native ORMを使用するアプリケーションがCoherenceキャッシュにアクセスできます。これらのクラスは、Coherenceキャッシュの動作が修正メソッドで構成されている場合に使用します。これらのクラスを使用して、「グリッド基盤のJPA構成」の説明と同じ方法で各永続クラスのキャッシュ・ストアまたはキャッシュ・ローダーを構成できます。
Coherenceキャッシュ構成ファイルcoherence-cache-config.xmlを使用して、キャッシュ・ストア・キャッシュ・スキームを定義し、デフォルトのCoherence設定をオーバーライドします。
構成では、ネイティブEclipseLink sessions.xmlファイルとproject.xmlファイルを使用します。sessions.xmlファイル、およびそこにリストされているすべてのデプロイメントXMLファイル(ユーザー定義の名前を持ちます)は、クラスパスで使用可能になっているか、META-INFディレクトリ内のJARファイルにパッケージ化されている必要があります。
適切なキャッシュ動作を定義するには、修正メソッドも構成する必要があります。詳細は、「修正メソッドの構成」を参照してください。
修正メソッドとは、EclipseLink記述子APIを使用してクラスに対するORMマッピング・メタデータをカスタマイズするメソッドです。メソッドは実行時に記述子がロードされる際にコールされます。TopLink Gridにより提供される修正メソッドの目的は、Coherenceキャッシュの使用方法を定義することです。修正メソッドは、TopLink Native ORMで@Customizer注釈にかわるものです。どちらの場合も同じ構成が生成されます。
toplink-grid.jarにあるTopLink Gridのカスタマイザ・クラス(CoherenceReadCustomizer、CoherenceReadWriteCustomizer、およびGridCacheCustomizer)は、適切なCoherenceキャッシュ動作を有効にするために選択できるafterLoad修正メソッドを提供します。
JDeveloperまたはEclipseLink Workbenchを使用して修正メソッドを選択できます。次の項では、JDeveloperで修正メソッドを構成する方法について説明します。EclipseLink Workbenchの説明は、このドキュメントでは述べません。
修正メソッドを構成するには、次の手順に従います。
JDeveloperの「構造」ペインで、目的のtlMap記述子名を展開します。
目的のTopLink記述子要素を右クリックします。「アドバンスト・プロパティ」を選択して「アドバンスト・プロパティ」ダイアログ・ボックスを開きます。「ロード後」チェック・ボックスを選択し、「OK」をクリックします。
tlMap構成ウィンドウの「ロード後」タブで、選択したTopLink記述子に使用するafterLoad修正メソッドを含むクラスの名前を入力します。クラス・ブラウザを使用してクラスを検索することもできます。図1-9に、tlMap構成ウィンドウの「ロード後」タブを示します。
図1-10に、CoherenceReadCustomizerクラスが選択されているクラス・ブラウザを示します。
tlMap構成ウィンドウの「ロード後」タブで、「Staticメソッド」ドロップダウン・リストから修正メソッドを選択します。Coherence Customizerクラスの場合、これはafterLoadメソッドになります。
coherence-cache-config.xmlファイルでは、キャッシュ・ローダーまたはキャッシュ・ストア・クラスを指定し、キャッシュ名とセッション名(つまりプロジェクト名)のパラメータを提供する必要があります。次の例は、クラス名(EclipseLinkNativeCacheStoreまたはEclipseLinkNativeCacheLoader)の変更以外に、キャッシュ・ローダーまたはキャッシュ・ストアを使用しているかどうかに応じてCoherenceキャッシュ構成に対して変更を行わないことを示しています。
例1-15は、EclipseLink Native ORMアプリケーションと通信できるキャッシュのcoherence-cache-config.xmlファイル内の構成を示しています。class-name要素は、EclipseLinkNativeCacheStoreクラスをキャッシュ・ストア・スキームとして識別します。param-value要素は、クラスに渡されるキャッシュ名とセッション(プロジェクト)名を指定します。
例1-15 統合EclipseLinkNativeCacheStoreの構成
...
<distributed-scheme>
<scheme-name>eclipselink-native-distributed-store</scheme-name>
<service-name>EclipseLinkNative</service-name>
<serializer>
<class-name>oracle.eclipselink.coherence.integrated.cache.WrapperSerializer</class-name>
</serializer>
<backing-map-scheme>
<read-write-backing-map-scheme>
<internal-cache-scheme>
<local-scheme/>
</internal-cache-scheme>
<!-- Define the cache scheme -->
<cachestore-scheme>
<class-scheme>
<class-name>oracle.eclipselink.coherence.integrated.EclipseLinkNativeCacheStore</class-name>
<init-params>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>{cache-name}</param-value>
</init-param>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>coherence-native-project</param-value>
</init-param>
</init-params>
</class-scheme>
</cachestore-scheme>
</read-write-backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
...
例1-16は、coherence-cache-config.xmlファイル内の統合EclipseLinkNativeCacheLoaderインスタンス構成を示しています。キャッシュ名({cache-name})およびセッション名(coherence-native-project)パラメータ値がクラスに渡されます。
例1-16 統合EclipseLinkNativeCacheLoaderの構成
...
<cachestore-scheme>
<class-scheme>
<class-name>oracle.eclipselink.coherence.integrated.EclipseLinkNativeCacheLoader</class-name>
<init-params>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>{cache-name}</param-value>
</init-param>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>coherence-native-project</param-value>
</init-param>
</init-params>
</class-scheme>
</cachestore-scheme>
...
この項では、Portable Object Format (POF)シリアライズを使用して、TopLink GridおよびCoherenceキャッシュを使用するアプリケーションのパフォーマンスを最適化する方法について説明します。
シリアライズとは、オブジェクトをバイナリ形式にエンコードするプロセスです。これは、ネットワークを介してデータを移動する必要がある場合のCoherenceの操作に不可欠な機能です。Portable Object Format (POF)は言語に依存しないバイナリ形式です。POFは領域と時間の両面で効率を向上させるように設計されており、Coherenceの使用時に不可欠なものとなっています。POFの使用には、パフォーマンス上のメリットから言語の非依存性まで、様々なメリットがあります。Coherenceで作業する際には、シリアライズ・ソリューションとしてPOFを詳細に検討することをお薦めします。
この項では、POFシリアライズの対象とするためにTopLinkアプリケーション・ファイルに加える必要がある変更および追加についてのみ説明します。POFの使用方法および構成の詳細は、『Oracle Fusion Middleware Oracle Coherenceでのアプリケーションの開発』のPortable Object Formatの使用方法に関する項を参照してください。
この項の内容は次のとおりです。
エンティティのシリアライズおよびデシリアライズの方法を指定するシリアライズ・ルーチンを実装する必要があります。これは、PortableObjectインタフェースを実装するか、com.tangosol.io.pof.PofSerializerインタフェースを使用してシリアライザを作成することで実行できます。
エンティティ・クラス・ファイルでのPortableObjectインタフェースの実装
com.tangosol.io.pof.PortableObjectインタフェースは、POFデータ・ストリームとの間で自身の状態を自己シリアライズおよびデシリアライズする機能を持つクラスを提供します。このインタフェースを使用するには、必須メソッドreadExternalおよびwriteExternalも実装する必要があります。
例1-17は、PortableObjectインタフェースを実装するエンティティ・クラス・ファイルの例を示しています。必須メソッドのreadExternalおよびwriteExternalも実装されていることに注目してください。
このクラスには、TradeオブジェクトとSecurityオブジェクトとのリレーションシップ・マッピングを定義する@OneToOne注釈が含まれていることにも注意してください。TopLinkでは、JPA仕様によって定義されているリレーションシップ・マッピング(1対1、1対多、多対多および多対多)がすべてサポートされています。これらのリレーションシップは、注釈として表すことができます。
例1-17 PortableObjectを実装するエンティティ・クラスの例
package oracle.toplinkgrid.codesample.pof.models.trader; import java.io.IOException; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id;import javax.persistence.OneToOne;import com.tangosol.io.pof.PofReader;import com.tangosol.io.pof.PofWriter;import com.tangosol.io.pof.PortableObject;/** * This class will not be stored within Coherence as Trades are not high * throughput objects in this model. * */ @Entitypublic class Trade implements Serializable, PortableObject{ /** * */ private static final long serialVersionUID = -244532585419336780L; @Id @GeneratedValue protected long id;@OneToOne(fetch=FetchType.EAGER)protected Security security; protected int quantity; protected double amount; public long getId() { return id; } public void setId(long id) { this.id = id; } public Security getSecurity() { return security; } public void setSecurity(Security security) { this.security = security; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } public double getAmount() { return amount; } public void setAmount(double amount) { this.amount = amount; }public void readExternal(PofReader pofreader) throws IOException{ id = pofreader.readLong(0); quantity = pofreader.readInt(2); amount = pofreader.readDouble(3); }public void writeExternal(PofWriter pofwriter) throws IOException{ pofwriter.writeLong(0, id); pofwriter.writeInt(2, quantity); pofwriter.writeDouble(3, amount); } }
エンティティに対するPOFSerializerの作成
PortableObjectインタフェースを実装するかわりに、com.tangosol.io.pof.PofSerializerインタフェースを実装して独自のシリアライザおよびデシリアライザを作成できます。このインタフェースには、シリアライズ・ロジックを、シリアライズするエンティティから外部化する手段が用意されています。これは、CoherenceでPOFを使用する場合に、クラスの構造を変更したくないときには特に役立ちます。POFSerializerインタフェースは、次のメソッドを提供します。
public Object deserialize(PofReader in)
public void serialize(PofWriter out, Object o)
キャッシュ構成ファイルで、操作するエンティティに対応するキャッシュ・マッピングを作成します。シリアライザ(com.tangosol.io.pof.ConfigurablePofContextなど)およびPOF構成ファイルpof-config.xmlを指定します。EclipseLinkキャッシュ・ストア(oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStoreなど)を<cachestore-scheme>属性内に指定します。
例1-18 キャッシュ構成ファイルの例
<?xml version="1.0"?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config http://xmlns.oracle.com/coherence/coherence-cache-config/1.0/coherence-cache-config.xsd">
<caching-scheme-mapping>
<cache-mapping>
<cache-name>ATTORNEY_JPA_CACHE</cache-name>
<scheme-name>eclipselink-jpa-distributed</scheme-name>
</cache-mapping>
<cache-mapping>
<cache-name>CONTACT_JPA_CACHE</cache-name>
<scheme-name>eclipselink-jpa-distributed-load</scheme-name>
</cache-mapping>
...
additional cache mappings
...
<caching-schemes>
<distributed-scheme>
<scheme-name>eclipselink-jpa-distributed-load</scheme-name>
<service-name>EclipseLinkJPA</service-name>
<serializer>
<instance>
<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
<init-params>
<init-param>
<param-type>String</param-type>
<param-value>trader-pof-config.xml</param-value>
</init-param>
</init-params>
</instance>
</serializer>
<backing-map-scheme>
<read-write-backing-map-scheme>
<internal-cache-scheme>
<local-scheme/>
</internal-cache-scheme>
</read-write-backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
<distributed-scheme>
<scheme-name>eclipselink-jpa-distributed</scheme-name>
<service-name>EclipseLinkJPA</service-name>
<serializer>
<instance>
<class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
<init-params>
<init-param>
<param-type>String</param-type>
<param-value>trader-pof-config.xml</param-value>
</init-param>
</init-params>
</instance>
</serializer>
<backing-map-scheme>
<read-write-backing-map-scheme>
<internal-cache-scheme>
<local-scheme/>
</internal-cache-scheme>
<!-- Define the cache scheme -->
<cachestore-scheme>
<class-scheme>
<class-name>oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStore</class-name>
<init-params>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>{cache-name}</param-value>
</init-param>
<init-param>
<param-type>java.lang.String</param-type>
<param-value>coherence-pu</param-value>
</init-param>
</init-params>
</class-scheme>
</cachestore-scheme>
</read-write-backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
</caching-schemes>
</cache-config>
POFシリアライズの対象とするエンティティ・クラスを指定するファイルを定義します。Coherenceにはデフォルトで、pof-config.xmlという名前のPOF構成ファイルが用意されています。このファイルを使用して、TopLinkクラスのtype-idsをエンティティ・クラスに割り当てます。
TopLink GridによりTopLink-Grid必須クラスへのtype-idの割当が簡単になります。POF構成ファイルでallow-interfaces要素がtrueに設定されている場合、複数のTopLink-Gridクラスに対して必要なtype-idエントリは1つのみです。
oracle.eclipselink.coherence.integrated.cache.TopLinkGridPortableObject - PortableObjectインタフェースのTopLink Gridアナログ。TopLinkGridPortableObjectインタフェースを実装するTopLink Gridは、TopLinkGridSerializerクラスでシリアライズされたPOFになります。これにより、allow-interfaces POF構成要素がtrueに設定されている場合は、このインタフェースのすべてのインプリメンタに対して単一のクラスを登録できます。
oracle.eclipselink.coherence.integrated.cache.TopLinkGridSerializer - TopLinkGridPortableObjectインタフェースのすべてのインプリメンタに関連付けられたシリアライザ。これにより、allow-interfaces POF構成要素がtrueに設定されている場合は、このインタフェースのすべてのインプリメンタに対して単一のクラスをPOF構成XMLファイルに登録できます。
例1-19は、AttorneyエンティティへのTopLinkGridPortableObjectおよびTopLinkGridSerializerシリアライザ・クラスの割当てを示しています。
例1-19 簡略化したPOF構成ファイル
<?xml version="1.0"?>
<pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config http://xmlns.oracle.com/coherence/coherence-pof-config/1.0/coherence-pof-config.xsd">
<user-type-list>
<!-- include all "standard" Coherence POF user types -->
<include>coherence-pof-config.xml</include>
<user-type>
<type-id>1163</type-id>
<class-name>oracle.toplinkgrid.codesample.pof.models.trader.Attorney</class-name>
</user-type>
...
additional type IDs for Entity classes
...
<user-type>
<type-id>1130</type-id>
<class-name>oracle.eclipselink.coherence.integrated.cache.TopLinkGridPortableO bject</class-name>
<serializer>
<class-name>oracle.eclipselink.coherence.integrated.cache.TopLinkGridSerialize r</class-name>
</serializer>
</user-type>
...
<allow-interfaces>true</allow-interfaces>
</pof-config>
|
注意: TopLink Grid POF構成には、 |
allow-interfacesをtrueに設定できない場合は、次のクラスに対して個別にtype-idエントリを定義する必要があります。
oracle.eclipselink.coherence.integrated.internal.cache.ElementCollectionUpdateProcessor: キャッシュ内のElementCollectionオブジェクトを更新する際にTopLink Gridで使用されるエントリ・プロセッサ。
oracle.eclipselink.coherence.integrated.internal.cache.RelationshipUpdateProcessor: グリッドに遅延ロードされた関連データを更新するために使用される内部ファイル。
oracle.eclipselink.coherence.integrated.internal.cache.VersionPutProcessor: グリッドに対するオプティミスティック・ロック対応の更新に使用される内部ファイル。
oracle.eclipselink.coherence.integrated.internal.cache.VersionRemoveProcessor: グリッドからのオプティミスティック・ロック対応の削除に使用される内部ファイル。
oracle.eclipselink.coherence.integrated.internal.cache.SerializableWrapper: 非POFシリアライズ用の汎用ラッパー・クラス。これは、適切な動的ラッパーが定義されていないために例外を生成する可能性があるノードをシリアライズするために提供されます。
oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor: オプティミスティック・ロックされたオブジェクトのconditional put中に使用されます。このクラスは、オブジェクトからバージョン値を抽出するために使用されます。
oracle.eclipselink.coherence.integrated.internal.querying.FilterExtractor: キャッシュに格納されているオブジェクトから値を抽出するためにフィルタによって使用されます。これは、属性アクセスとメソッド・アクセスの両方をサポートしています。
oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$SubClassOf: 内部クラス。これは、エンティティ・タイプに基づいてフィルタするFilter拡張です。多相問合せからスーパークラスを取り除きます。type-idは、この操作を使用している場合にのみ、このクラスに対して必要です。
oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$$IsNull: 内部クラス。IsNullは、明示的なメソッド名のかわりにValueExtractorのサポートが提供されること以外は、CoherenceのIsNullFilterと同等です。type-idは、この操作を使用している場合にのみ、このクラスに対して必要です。
oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$$IsNotNull: 内部クラス。IsNotNullは、明示的なメソッド名のかわりにValueExtractorのサポートが提供されること以外は、CoherenceのIsNotNullFilterと同等です。type-idは、この操作を使用している場合にのみ、このクラスに対して必要です。
例1-20は、TopLink Gridサポート・ファイルの定義を含むPOF構成ファイルの例を示しています。
例1-20 TopLinkクラスの定義を含むPOF構成ファイルの例
...additional type IDs for Entity classes... <user-type> <type-id>1144</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.cache.ElementCollectionUpdateProcessor</class-name></user-type> <user-type> <type-id>1143</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.querying.FilterExtractor</class-name></user-type> <user-type> <type-id>1142</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor</class-name></user-type> <user-type> <type-id>1141</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.cache.VersionPutProcessor</class-name></user-type> <user-type> <type-id>1140</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.cache.VersionRemoveProcessor</class-name></user-type> <user-type> <type-id>1139</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.cache.RelationshipUpdateProcessor</class-name></user-type> <user-type> <type-id>1138</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.cache.SerializableWrapper</class-name></user-type> <user-type> <type-id>1137</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$SubClassOf</class-name></user-type> <user-type> <type-id>1136</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$$IsNull</class-name></user-type> <user-type> <type-id>1135</type-id><class-name>oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$$IsNotNull</class-name></user-type> </user-type-list> <allow-interfaces>false</allow-interfaces> </pof-config>
この項では、バイト・コード・ウィービング、遅延ロード、ニア・キャッシュ、およびキャッシュ構成でのTopLink Gridの使用方法に関するベスト・プラクティスの推奨事項について説明します。
この項の内容は次のとおりです。
バイト・コード・ウィービングは、コンパイル済Javaクラスのバイト・コードを変更する手法です。バイト・コード・ウィービングを構成して、1対1および多対1関係の遅延ロードのサポート、属性レベルの変更追跡、フェッチ・グループなど、いくつかのEclipseLink JPAパフォーマンス最適化を有効にできます。
ウィービングは、エンティティ・クラスのロード時に動的に実行するか、ビルド・プロセスの一部として静的に実行できます。静的バイト・コード・ウィービングは、EclipseLinkで提供されるweaverタスクを使用してAntビルドに組み込むことができます。
動的バイト・コード・ウィービングは、Oracle WebLogicなどのJava EE 5対応アプリケーション・サーバーで自動的に有効になります。ただし、Java SEでは、JRE 1.5 javaagent JVMコマンドライン引数を使用して明示的に有効にする必要があります。Oracle TopLinkソリューション・ガイドのウィービングの使用に関する項を参照してください。
Coherenceキャッシュ・サーバーでバイト・コード・ウィービングを有効にするには、-javaagent:<PATH>\eclipselink.jarでJava VMを起動する必要があります。Java SEクライアント・アプリケーションは、-javaagent引数を指定して実行する必要があります。
静的および動的バイト・コード・ウィービングの構成と無効化の詳細は、Oracle TopLinkソリューション・ガイドのウィービングの使用に関する項を参照してください。
遅延ロードは、必要になるまでデータベースへのオブジェクトの問合せを遅延するために使用する手法です。これにより、アプリケーションによってロードされるデータ量を削減し、スループットを向上できます。TopLink Grid JPAまたはネイティブORMアプリケーションでは、すべての関係を遅延ロードする必要があります。JPAの1対多および多対多関係では遅延ロードがデフォルトですが、1対1および多対1関係では即時です。これらの関係タイプでは、遅延ロードを明示的に選択する必要があります。たとえば、関係注釈の多くでは遅延ロードを属性として指定できます。
... @ManyToOne(fetch=FetchType.LAZY) private Publisher parent ...
効率を最大化するために、TopLink GridがCoherenceキャッシュに格納するすべての1対1および多対1エンティティ関係に遅延ロードを指定する必要があります。遅延ロードは、EclipseLinkのバイト・コード・ウィービングを通じて実装され、Java EE 5準拠アプリケーション・サーバーで実行されていない場合は明示的に有効にする必要があります。詳細は、「バイト・コード・ウィービングでのコンパイル済Javaクラスの変更」を参照してください。
ニア・キャッシュは、Oracle Coherenceによって提供される標準キャッシュ構成の1つです。ニア・キャッシュを使用すると、オブジェクトを繰り返し取得する場合にネットワーク・アクセスを回避することでスループットを向上することができます。たとえば、ユーザーが特定のWebサーバーに固定されている環境では、ニア・キャッシュによりパフォーマンスが向上する可能性があります。
ニア・キャッシュはハイブリッド・キャッシュであり、サイズの制限された高速なデータ・アクセスを提供するフロント・キャッシュと、スケーラブルで要求に応じてロード可能であり、フェイルオーバー保護を提供する容量の大きいバック・キャッシュで構成されます。
TopLink Gridを使用するアプリケーションの場合、Oracle Coherenceを使用する他のアプリケーションと同じ方法でニア・キャッシュを構成します。ニア・キャッシュの詳細は、『Oracle Fusion Middleware Oracle Coherenceでのアプリケーションの開発』のニア・キャッシュに関する項およびニア・キャッシュ・スキームの定義に関する項を参照してください。
|
注意: ニア・キャッシュは、Coherenceキャッシュの これは、JPQL問合せを使用している場合に問題となることもあります。TopLink Gridのグリッド読取り構成またはグリッド・エンティティ構成では、JPQL問合せは |
TopLink GridをCoherenceキャッシュおよびCoherence*Webを使用するアプリケーションとともに使用する場合、エンティティに対するTopLink GridキャッシュとCoherence*Webキャッシュに異なる構成プロパティを適用することが必要になることがあります。一連のキャッシュを指定および構成する最も効率的な方法は、ワイルドカード文字(*)を使用することです。ただし、これは両方のキャッシュ・セットに一致します。Coherence*Webキャッシュをエンティティ・キャッシュと区別するには、エンティティにのみ一致するワイルドカード・パターンを作成する必要があります。これを実行する1つの方法は、エンティティ・キャッシュ名に一意の接頭辞を付加することです。
次の手順は、TopLink Grid対応クラスに特定の接頭辞を付加するためにカスタム・セッション・カスタマイザを作成して使用する方法を示しています。
指定した接頭辞をTopLink対応クラスに付けるセッション・カスタマイザ・クラスを作成します。
例1-21は、EclipseLink SessionCustomizerクラスを実装するカスタム・セッション・カスタマイザ・クラスであるCacheNamePrefixCustomizerを示しています。このクラスは、TopLink対応クラスに追加される接頭辞を表すPREFIX_PROPERTY myapp.cache-prefixを定義します。このプロパティの値は、persistence.xmlファイルで指定することも(手順2で説明)、Persistence.createEntityManagerFactoryメソッドにオプションのプロパティ・マップで渡すこともできます。
例1-21 接頭辞を付加するセッション・カスタマイザ
import java.util.Collection;
import oracle.eclipselink.coherence.IntegrationProperties;
import oracle.eclipselink.coherence.integrated.cache.CoherenceInterceptor;
import oracle.eclipselink.coherence.integrated.internal.cache.CoherenceCacheHelper;
import org.eclipse.persistence.config.SessionCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.sessions.Session;
public class CacheNamePrefixCustomizer implements SessionCustomizer {
private static final String PREFIX_PROPERTY = "myapp.cache-prefix";
public void customize(Session session) throws Exception {
// Look up custom persistence unit cache prefix property
String prefix = (String) session.getProperty(PREFIX_PROPERTY);
if (prefix == null) {
throw new RuntimeException(
"Cache name prefix customizer configured but prefix property '" +
PREFIX_PROPERTY + "' not specified");
}
// Iterate over all entity descriptors
Collection<ClassDescriptor> descriptors = session.getDescriptors().values();
for (ClassDescriptor classDescriptor : descriptors) {
// If entity is TopLink Grid-enabled, prepend cache name with prefix
if (CoherenceInterceptor.class.equals(classDescriptor.getCacheInterceptorClass())) {
String cacheName = CoherenceCacheHelper.getCacheName(classDescriptor);
classDescriptor.setProperty(IntegrationProperties.COHERENCE_CACHE_NAME, prefix + cacheName);
}
}
}
}
persistence.xmlファイルを編集して接頭辞プロパティの値を宣言します。
次の例では、persistence.xmlファイル内で接頭辞プロパティmyapp.cache-prefixの値としてMyApp_が定義されています。myapp.cache-prefix接頭辞プロパティは、カスタム・セッション・カスタマイザ・ファイルで定義されます。
<property name="myapp.cache-prefix" value="MyApp_"/>
EclipseLink SessionCustomizerクラスの詳細は、http://www.eclipse.org/eclipselink/を参照してください。
persistence.xmlファイルを編集し、カスタム・セッション・カスタマイザ・クラスをeclipselink.session.customizerコンテキスト・プロパティの値として追加します。
<property name="eclipselink.session.customizer" value="CacheNamePrefixCustomizer"/>
coherence-cache-config.xmlファイルを編集し、キャッシュ・マッピングにワイルドカード文字を含む接頭辞の名前を追加します。
<cache-mapping>
<cache-name>MyApp_*</cache-name>
<scheme-name>eclipselink-distributed-readonly</scheme-name>
</cache-mapping>
エンティティ・キャッシュに指定されたデフォルト名のオーバーライドが必要になる場合があります。TopLink Gridでは、エンティティ・キャッシュ名はデフォルトでエンティティ名になります。次のリストは、キャッシュ名の決定方法とそれを明示的に変更する方法を示しています。
キャッシュ名はデフォルトで設定することも、明示的に設定することもできます。
デフォルト: キャッシュ名はデフォルトでエンティティ名になります。一方、エンティティ名は、デフォルトで設定することも明示的に設定することもできます。
デフォルト: エンティティ名はデフォルトでクラスの短縮名になります。
明示的: エンティティ名は、@Entity注釈のnameプロパティを使用することで明示的に設定できます。
明示的: キャッシュ名は、@Property注釈を使用することで明示的に設定できます。
たとえば、次のコード部分は、Employeeクラスを示しています。デフォルトでは、エンティティ・キャッシュ名はEmployeeになります。ただし、@Property注釈を使用することで、Employeeエンティティ・キャッシュの名前を強制的にEMP_CACHEにすることができます。
import static oracle.eclipselink.coherence.IntegrationProperties.COHERENCE_CACHE_NAME;
import org.eclipse.persistence.annotations.Property;
...
@Entity(name="Emp")
@Property(name=COHERENCE_CACHE_NAME, value="EMP_CACHE")
public class Employee implements Serializable {
...
コードでエンティティ名がEmpに明示的に指定されていることに注意してください。name="Emp"値が指定されていなければ、エンティティの名前にはクラスの短縮名であるEmployeeがデフォルトで使用されます。