8.7.1 キャッシュ機能の処理
キャッシュ機能を使用している場合,同じエンティティに対して読み込みをすると,データベースではなく,キャッシュからデータが取得されるようになります。キャッシュ機能の処理の流れ,キャッシュの登録および更新のタイミング,およびキャッシュの更新処理の流れを説明します。
(1) キャッシュ機能の処理の流れ
キャッシュ機能の処理の流れについて次の図に示します。
上記の図について説明します。
-
エンティティの読み込み処理
findなどのメソッドで最初にエンティティを読み込むときは次の流れで処理されます。
-
エンティティの読み込み処理をします。
-
データベースからデータを取得します。
-
取得したデータのエンティティオブジェクトをキャッシュに登録します。
-
エンティティがリレーションシップを持つ場合でリレーションシップ先のエンティティを取得するとき,目的のエンティティがキャッシュに存在すると,データベースにアクセスしないでキャッシュのエンティティを参照します。
キャッシュは,永続化コンテキスト単位で存在します。
(2) キャッシュの登録および更新のタイミング
キャッシュへの登録および更新は次に示すタイミングで実施されます。
-
キャッシュの登録のタイミング
対象となるキャッシュが存在しない状態でのエンティティオブジェクトの読み込み時(find操作)
-
キャッシュの更新のタイミング
-
エンティティのリフレッシュ処理時(refresh操作)
-
トランザクションのコミット時
-
楽観的ロックの処理で例外が発生した場合
なお,楽観的ロックの処理でOptimisticLockException例外が発生した場合には,キャッシュに登録されているエンティティオブジェクトは削除されます。
-
(3) キャッシュの更新処理の流れ
キャッシュの更新処理の流れについて次の図に示します。
図について説明します。
-
エンティティオブジェクトに対して,次の操作を実施します。
-
refresh操作
-
トランザクションのコミット
-
-
refresh操作の場合は,データベースにアクセスします。
-
永続化コンテキストにあるデータをキャッシュに登録して,キャッシュのデータを更新します。
なお,JPQLを実行した場合にもキャッシュは登録されます。登録されるタイミングは,対象となるキャッシュが存在しない状態でJPQLを実行した場合です。JPQLでもキャッシュのデータを使用しますが,キャッシュのデータの有無に関係なく,データベースのアクセスが発生します。このため,キャッシュによる処理性能の向上は期待できません。詳細については,(4)を参照してください。
キャッシュは,エンティティのオブジェクト単位で情報を保持しているため,クエリの実行時に返されるオブジェクトがエンティティ自身の場合には,キャッシュへの更新が実行されます。それ以外のフィールドを指定するような場合では,更新はされません。キャッシュの更新が有効になる場合と,ならない場合のJQPLの例を次に示します。
-
キャッシュの更新が有効に行われるJPQLの例
SELECT emp FROM Employee AS emp
-
キャッシュの更新がされないJPQLの例
SELECT emp.id, emp.name, emp.address FROM Employee AS emp
(4) JPQLとキャッシュの関係
JPQLでエンティティオブジェクト全体を取得するような場合,キャッシュに登録されている情報が存在すればキャッシュの情報を取得します。CJPAプロバイダのキャッシュ機能では,対象となるエンティティを特定するためのIDであるプライマリキーが必要になります。プライマリキーを取得するには,JPQLの結果を取得する必要があり,この際にデータベースへのアクセスが発生します。データベースへのアクセスの結果から,プライマリキーを抽出して,キャッシュからエンティティオブジェクトを取得します。また,キャッシュに対象となるデータが存在しない場合は,データベースの情報からエンティティを作成します。
JPQLでは,キャッシュのデータの有無に関係なく必ずデータベースへのアクセスが発生します。そのため,JPQLの場合,キャッシュによる性能向上は望めません。