この章では、JPAの共有データベースでキャッシュを使用することを可能にするTopLinkデータベース変更通知(DCN)について説明します。
この章の内容は次のとおりです。
ユース・ケース
ユーザーが、JPAアプリケーションで共有キャッシュを使用したいと考えていますが、外部アプリケーションによって同じデータベース・データが更新されてしまうか、キャッシュがクラスタ環境にあります。キャッシュには失効データが残ってしまう場合があります。
解決方法
TopLinkには、データベースがTopLinkにデータベースの変更を通知できるようにするAPIが用意されています。変更されたオブジェクトは、TopLinkの共有キャッシュで無効にできます。失効したデータは、他のアプリケーションがデータベース内の同じデータにアクセスする場合でも破棄されます。
コンポーネント
Oracle 11gR2 (11.2) (以上の)データベース
TopLink 12c (12.1.2.0.0)以上。
注意: 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のデータベース変更通知によって提供されます。DCNでは、JPA環境で共有キャッシュを使用できます。
注意: データベース変更通知は、Oracle Databaseの連続問合せ通知機能によって提供される機能の拡張版です。詳細は、『Oracle Database JDBC開発者ガイド』の連続問合せ通知に関する項を参照してください。 |
EclipseLinkのデータベース変更通知は、Oracle Databaseの連続問合せ通知機能によって提供される機能の拡張版です。連続問合せ通知の機能の1つは、表の中の行が変更されたときにデータベース・イベントが発生することがこの機能によって許可されることです。
変更を検出するために、EclipseLink DCNはROWID
を使用し、プライマリ表の行レベルの変更を通知します。EclipseLinkでは、DCN対応のクラスのすべての問合せにROWID
を含めます。EclipseLinkでは、Insert操作後にオブジェクトのROWID
も選択します。EclipseLinkでは、オブジェクトId
のみでなく、ROWID
のキャッシュ索引も維持します。EclipseLinkは、トランザクションを処理しているサーバーでキャッシュが無効にされないよう、トランザクションごとに1回データベースのトランザクションIDも選択します。
EclipseLink DCNは、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ファイルに含めることができます。
注意: <exclude-unlisted-classes> 要素は、Java SE環境で使用するようには意図されていません。 |
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のデータベース変更通知のリスナーです。これによりデータベース・イベントにより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がデフォルトのプロバイダであるコンテナで実行される場合、<provider> タグはオプションです。 |
例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
注釈を追加します。
Oracle DCNでは、プライマリ表のイベントのみをリスニングします。セカンダリ表またはリレーションシップ表の変更は追跡しません。この理由は、Oracle DCNがROWID
のみを追跡し、プライマリ表、セカンダリ表およびリレーションシップ表のROWID
には相関関係がないためです。したがって、セカンダリ表またはリレーションシップ表が変更されたときにイベントを受け取るには、プライマリ表のバージョンを変更してイベントが返されるようにする必要があります。
EclipseLinkのデータベース変更通知には次の制約があります。
プライマリ表で@Version
注釈が使用され更新されないかぎり、オブジェクトのセカンダリ表が変更されてもその無効化はトリガーされません。
プライマリ表で@Version
注釈が使用され更新されないかぎり、オブジェクトのOneToMany
、ManyToMany
およびElementCollection
のリレーションシップが変更されてもその無効化はトリガーされません。
この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。
『Oracle Database JDBC開発者ガイド』の連続問合せ通知に関する項
「EclipseLink/Examples/JPA/DCN」: このページでは、DCNを採用しているJPA環境でのキャッシュ共有の例を説明しています。例を実行するサンプル・ファイルおよび手順が含まれています。EclipseLinkのドキュメントを参照してください。