この章では、JPAの共有データベースでキャッシュを使用することを可能にするOracle Database連続問合せ通知(CQN)に対するTopLinkのサポートについて説明します。
|
注意: Oracle Database連続問合せ通知は、以前は、Oracle Database変更通知としても知られていました。 |
この章の内容は次のとおりです。
ユース・ケース
ユーザーが、JPAアプリケーションで共有キャッシュを使用したいと考えていますが、外部アプリケーションによって同じデータベース・データが更新されてしまうか、キャッシュがクラスタ環境にあります。キャッシュには失効データが残ってしまう場合があります。
解決方法
Oracle Databaseには、データベースに対する変更をアプリケーションが登録できるAPIが用意されています。TopLinkでは、共有キャッシュで変更されたオブジェクトを無効にするために、Oracle Databaseへの登録とデータベースの変更イベントの処理をサポートしています。
コンポーネント
Oracle 11gR2 (11.2) (以上の)データベース
TopLink 12c (12.1.2)以上。
|
注意: TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。 |
EclipseLinkライブラリ: eclipselink.jar。
JDBCライブラリ: ojdbc6.jar。
JPAライブラリ: persistence.jar。
例
JPAを使用するアプリケーションで連続問合せ通知および共有キャッシュの使用方法を示すサンプル・ファイルについては、EclipseLinkのドキュメントの「EclipseLink/Examples/JPA/DCN」を参照してください。
http://wiki.eclipse.org/EclipseLink/Examples/JPA/DCN
EclipseLinkには、データベースのオブジェクトとリレーションシップに対するアクセスを減らす共有(L2)オブジェクト・キャッシュが用意されています。このキャッシュはデフォルトで有効で、他のアプリケーションまたはクラスタ環境において別のサーバーにある同じアプリケーションが、データベースの内容が直接変更しないかぎり通常は問題にはなりません。これによりキャッシュに無効なデータが生じる場合があります。
データベースの内容が変更された場合に、キャッシュの内容がデータベースと同期されることを保証するメカニズムが必要になります。このメカニズムは、EclipseLinkのOracle連続問合せ通知に対するサポートで提供されます。CQNによりJPA環境で共有キャッシュの使用が可能になります。
|
注意: Oracle Database連続問合せ通知の機能の詳細は、『Oracle Database開発者ガイド』の連続問合せ通知(CQN)の使用に関する項を参照してください。『Oracle Database JDBC開発者ガイド』の連続問合せ通知に関する項も参照してください。 |
EclipseLinkでは、表の内容が変更されたときに、データベースからイベントを受け取る、Oracle Database連続問合せ通知への登録をサポートしています。変更の検出に、CQNはROWIDを使用し、プライマリ表の列レベルの変更を通知します。EclipseLinkでは、CQNが有効なクラスのすべての問合せにROWIDを含めます。EclipseLinkでは、Insert操作後にオブジェクトのROWIDも選択します。EclipseLinkでは、オブジェクトIdのみでなく、ROWIDのキャッシュ索引も維持します。EclipseLinkは、トランザクションを処理しているサーバーでキャッシュが無効にされないよう、トランザクションごとに1回データベースのトランザクションIDも選択します。
EclipseLinkは、OracleChangeNotificationListener (org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener)リスナー・クラスを介して有効にされます。リスナーはOracle JDBCと統合して、データベースの変更イベントを受け取ることができます。リスナーを有効にするには、persistence.xmlファイルでeclipselink.cache.database-event-listenerプロパティの値としてOracleChangeNotificationListenerクラスへの完全なパスを指定します。
デフォルトでは、ドメインのすべてのエンティティに対して変更通知が登録されます。ただし、変更通知は、JavaファイルのCache注釈のdatabaseChangeNotificationType (org.eclipse.persistence.annotations.DatabaseChangeNotificationType)属性でタグ付けして、特定のクラスを選んで無効にすることもできます。この属性の値によって、エンティティが使用するデータベースに対する変更通知の種類が決定されます。databaseChangeNotificationType属性のデフォルト値はInvalidateです。クラスの変更通知を無効にするには、属性の値をNoneに設定します。
databaseChangeNotificationType属性は、永続性ユニットにデータベースの変更イベントを受け取るOracleChangeNotificationListenerクラスなどのデータベース・イベント・リスナーが構成されている場合のみ該当します。これによりデータベースに変更があったときに、EclipseLinkのキャッシュを無効にしたり、更新できます。
トランザクションでは、(失効データに対する書込みは失敗し、キャッシュが自動的に無効になる)オプティミスティック・ロックを使用することを強くお薦めします。エンティティに@Version注釈を含めると、プライマリ表のバージョン列には常に更新され、オブジェクトは常に無効化されます。
この項では、JPA環境で共有キャッシュを有効にする次のタスクについて説明します。
このソリューションでは、関心のある表がOracle 11gR2 (11.2)以上のデータベースに含まれ、それで作業していることが前提です。
他の許可に加え、データベース・ユーザーには、CHANGE NOTIFICATION権限が付与されている必要があります。これを実行するには、SYSなどのDBA権限を持っているか、データベース管理者にそれを適用してもらう必要があります。
grant change notification to user
次の例では、ユーザーSCOTTに変更通知権限を付与する例を示します。
...
define user="SCOTT"
define pass="tiger"
grant create session, alter session to &&user
/
grant resource, connect to &&user
/
grant select any dictionary to &&user
/
grant select any table to &&user
/
grant change notification to &&user
/
...
EclipseLinkライブラリのeclipselink.jar、JDBCライブラリのojdbc6.jar、JPAライブラリのpersistence.jarおよびドメイン・クラスがクラスパスにあることを確認します。
デフォルトでは、ドメインのすべてのエンティティが変更通知に参加します。参加するエンティティを制限するには、いくつかの方法があります。たとえば、エンティティ・クラスをorm.xmlファイルの<entity class...>要素、persistence.xmlファイルの<exclude-unlisted-classes>要素、またはJARファイルに含めて示すことができます。
|
注意:
|
JavaファイルでCache注釈属性を使用して、エンティティ・クラスを除外することも可能です。詳細は、22.2.6.2項「変更通知からのクラスの除外(オプション)」を参照してください。
persistence.xmlファイルで<class>要素を使用して、エンティティ・クラスを指定することも可能です。次の例は、modelパッケージのOrder、OrderLineおよびCustomerクラスが変更通知に参加することを示します。完全なpersistence.xmlファイルの例は、例22-1を参照してください。
... <class>model.Order</class> <class>model.OrderLine</class> <class>model.Customer</class> ...
データベース・イベント・リスナーを指定するには、eclipselink.cache.database-event-listenerプロパティを使用します。連続問合せ通知のリスナーは、org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListenerクラスです。これによりデータベース・イベントによりEclipseLinkのキャッシュが無効になります。
次に、OracleChangeNotificationListenerクラスにeclipselink.cache.database-event-listenerプロパティを構成した例を示します。完全なpersistence.xmlファイルの例は、例22-1を参照してください。
...
<properties>
<property name="eclipselink.cache.database-event-listener" value="org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener"/>
</properties>
...
次を使用することも可能です。
<property name="eclipselink.cache.database-event-listener" value="DCN">
persistence.xmlファイルの完全な例を例22-1に示します。変更通知に参加するクラスは、modelパッケージのOrder、OrderLineおよびCustomerクラスです。eclipselink.cache.database-event-listenerプロパティは、OracleChangeNotificationListenerクラスの完全パスに設定されます。
|
注意: EclipseLinkがデフォルトのプロバイダであるコンテナで実行される場合、 |
例22-1 persistence.xmlのサンプル・ファイル
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_0.xsd"
version="2.0">
<persistence-unit name="acme" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>model.Order</class>
<class>model.OrderLine</class>
<class>model.Customer</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.cache.database-event-listener" value="DCN"/>
</properties>
</persistence-unit>
</persistence>
通常、変更通知に参加する場合、データベース表に対応するJavaクラスは変更する必要がありません。ただし、@Version注釈でオプティミスティック・ロックを設定することが強く推奨されます。
永続性ユニットに列挙されるクラスを除外したい場合は、Javaファイルでタグ付けします。EclipseLinkはプライマリ表でのみ変更を追跡します。セカンダリ表も追跡されるよう変更するには、Javaファイルにそれを示します。
失効データに対する書込みが失敗し、キャッシュを自動的に無効にするオプティミスティック・ロックを使用することを強くお薦めします。エンティティに@Version注釈を含めると、プライマリ表のバージョン列は常に更新されるので、古いバージョンのオブジェクトは常に無効化されます。
例22-2では、@Version注釈はCustomerエンティティに定義されています。versionの変数としてgetterおよびsetterが定義されていることに注意してください。
例22-2 @Version注釈の定義
...
@Entity
@Table(name="DBE_CUSTOMER")
public class Customer implements Serializable {
@Id
@GeneratedValue(generator="CUST_SEQ")
@TableGenerator(name="CUST_SEQ")
@Column(name="CUST_NUMBER")
private long id;
@Version
private long version;
...
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
...
Cache注釈のdatabaseChangeNotificationType属性を使用すると、変更通知を必要としないクラスを指定できます。変更通知からクラスを除外するには、次の例のとおり、属性をDatabaseChangeNotificationType.NONEに設定します。
...
@Entity
@Cache(databaseChangeNotificationType=DatabaseChangeNotificationType.NONE)
public class Order {
...
EclipseLinkはプライマリ表でのみ変更を追跡します。セカンダリ表で更新が発生する場合、EclipseLinkはオブジェクトを無効にしません。セカンダリ表でも同様に追跡するには、エンティティに@Version注釈を追加します。
CQNでは、プライマリ表のイベントのみをリスニングします。セカンダリ表またはリレーションシップ表の変更は追跡しません。これは、Oracle CQNはROWIDのみ追跡し、プライマリ表、セカンダリ表およびリレーションシップ表のROWIDには相関関係がないためです。したがって、セカンダリ表またはリレーションシップ表が変更されたときにイベントを受け取るには、プライマリ表のバージョンを変更してイベントが返されるようにする必要があります。
EclipseLinkの連続問合せ通知のサポートには、次の制限があります。
プライマリ表で@Version注釈が使用され更新されないかぎり、セカンダリ表のオブジェクトが変更されてもその無効化はトリガーされません。
プライマリ表で@Version注釈が使用され更新されないかぎり、オブジェクトのOneToMany、ManyToManyおよびElementCollectionのリレーションシップが変更されてもその無効化はトリガーされません。
この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。
『Oracle Database開発者ガイド』の連続問合せ通知(CQN)の使用に関する項
『Oracle Database JDBC開発者ガイド』の連続問合せ通知に関する項
「EclipseLink/Examples/JPA/DCN」: このページでは、DCNを採用しているJPA環境でのキャッシュ共有の例を説明しています。例を実行するサンプル・ファイルおよび手順が含まれています。EclipseLinkのドキュメントを参照してください。