Grailsアプリでは、追加することでドメインクラスごとに第2レベルのキャッシュを有効にすることを理解しています
_static mapping {
cache true
}
_
デフォルトでは、第2レベルのキャッシュはget()
が呼び出された場合にのみ使用されますが、クエリに_cache true
_を追加することで、条件クエリや動的ファインダーにも使用できます。
ただし、クエリキャッシュがどのように機能するかはまだわかりません。私の最善の推測はそれです:
Author.findByName('bob', [cache: true])
のようなクエリが実行される前に、ドメインクラス(作成者)、クエリ(findByName)、およびクエリパラメータ( 'bob')に基づいてキャッシュキーが計算されます。そのキーが作成者クエリキャッシュで見つかった場合、クエリを実行する代わりに、キャッシュされた結果が返されますこれは、Bookインスタンスを返すクエリがAuthorテーブルに結合する可能性があると考えるまでは合理的と思われます。その場合、作成者が保存、削除、または更新されるときに、BookとAuthorの両方のクエリキャッシュをフラッシュする必要があります。これにより、クエリキャッシュが1つだけで、キャッシュされたドメインクラスが保存されるたびにクリアされるのではないかと思われます。
Grailsのドキュメントでは、次のように述べています
Hibernateの第2レベルのキャッシュを使用してインスタンスをキャッシュする機能に加えて、オブジェクトのコレクション(関連付け)をキャッシュすることもできます。
例えば:
_class Author {
static hasMany = [books: Book]
static mapping = {
cache true // Author uses the 2nd level cache
books cache: true // associated books use the 2nd level cache
}
}
class Book {
static belongsTo = [author: Author]
static mapping = {
cache true // Book uses the 2nd level cache
}
}
_
上記の構成は理にかなっていますか?つまり、著者と本自体が第2レベルのキャッシュを使用している場合、著者と本の関連付けにも第2レベルのキャッシュを使用させることにメリットはありますか?
最後に、第2レベルのクエリキャッシュの使用について このアドバイス を読みました。これは、ドメインクラスの変更頻度が低い場合にのみ使用する必要があることを示しています。 get()
操作に対して第2レベルのキャッシュを有効にすべきではない状況、つまり、ドメインクラスに以下を追加しない理由はありますか?
_static mapping = {
cache true // Book uses the 2nd level cache
}
_
パート1:
Hibernateは正しいことをします。クエリキャッシュはエンティティごとではありません。クエリに特定の領域を設定しない限り、すべてのクエリで共有される単一のクエリキャッシュ領域があります。テーブルが更新されるたびに、タイムスタンプキャッシュ内のそのタイムスタンプが更新されます。クエリが実行されるたびに、クエリが検索する各テーブルのタイムスタンプが、キャッシュされた結果のタイムスタンプと比較されます。そしてもちろん、キャッシュされた結果は、そのタイムスタンプがすべてのテーブルのタイムスタンプよりも新しい場合にのみ返されます。
パート2:
はい、それは理にかなっています。著者のキャッシュは、ID456の著者の名前が「foo」で生年月日が1975/07/19であることを覚えています。著者テーブルに保存されているデータのみが記憶されます。したがって、関連付けをキャッシュすることも役立ちます。author.getBooks()
を呼び出すときに著者の本のセットを取得するために追加のクエリを作成する代わりに、Hibernateはそのキャッシュから著者の本のIDを取得します。次に、各ブックを第2レベルのキャッシュからロードします。ただし、必ずブックをキャッシュしてください。
パート3:
私はいくつかの理由を想像することができます: