1


私はこの問題で数日間壁に頭をぶつけてきました。

Infinispanを使用して、Hibernateの第2レベルのキャッシュを実装しようとしています。アプリケーションはJBossAS6で実行されており、JTAトランザクションを使用しています。

私たちのpersistence.xmlには次のものがあります:

...
<!-- JTA configurations -->
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
<property name="current_session_context_class" value="jta" />

<!-- Infinispan configurations -->
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />

<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.InfinispanRegionFactory"/>
<property name="hibernate.cache.infinispan.cachemanager" value="java:CacheManager/entity"/>
...

ここで定義されているように:

私たちの理解では、これは次のことを行うために必要な種類のキャッシュです。

ユースケース1: 参照データを保持するデータベースにレコードがあります。このデータは長期間変更されません(私たちは願っています:))。

これらのレコードは多くのクエリが実行される可能性があるため、キャッシュしたいと思います。また、ユーザーがこのデータをクエリするときに、キャッシュする必要があるため、DBに移動する必要はありません。

この場合、キャッシュタイプはクエリキャッシュですか、それともエンティティキャッシュですか?クエリは常に同じであるため、queクエリは常に同じ結果を返すことになっているため、クエリキャッシュであると理解しています。

私の質問:

List<MyEntity> list = session.createCriteria(MyEntity.class)
        .add(Restrictions.eq("id", 1))
        .setCacheable(true)
        .list();

ユースケース2: ユーザーがDBから特定のレコードを取得し、それを更新する場合があります。このエンティティ(またはエンティティのリスト)をユーザーのセッション(ログインセッション)キャッシュに保存する必要があるため、ユーザーがクライアントでこのエンティティを更新した場合、更新前に選択する必要はありません。この場合、特定のエンティティを保存しているので、エンティティのキ​​ャッシュと見なされますよね?保存したい場合

そのために私たちは使用しています:

@Cacheable (true)
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class MyEntity implements Serializable 
{
...
}

私はこれらの仮定を正しく行っていますか?そうでない場合、ここでのアプローチは何ですか?私はこれから大きな混乱を引き起こしていると思います。

4

2 に答える 2

1

2番目のレベル(エンティティ)のキャッシュは、(より単純にするために)キーとしてのIDに基づくマップです。したがって、参照データが他のエンティティで「参照」されるたびに、エンティティマネージャは、DBに移動する前に、まずデータがキャッシュに存在するかどうかを確認します。

クエリキャッシュは、クエリの結果(ID)エンティティのキ​​ャッシュです。次に、IDに基づいて、対応するエンティティを取得します(できれば、エンティティキャッシュから...)。そのため、エンティティを第2レベルのキャッシュにキャッシュしておく必要があります。

最初のユースケースでは、データを参照します。エンティティにキャッシュ可能として注釈を付け、読み取り専用戦略を使用する必要があります。エンティティマネージャーは、ロード時に参照データを参照エンティティに配置するか、find(clazz、id)を使用して第2レベルのキャッシュから参照データを取得します。

ケース2はもう少し注意が必要です。「セッション」スコープのキャッシュはありません(中間結果をユーザーセッションにバインドし続ける必要がある場合は、SFSBまたは上位レベルのセッションメカニズムを介して自分で管理する必要があります)。エンティティをキャッシュ可能にすると、サーバー上のすべてのユーザーに対してキャッシュされ、エンティティマネージャーコンテキストにはユーザーとの直接リンクがありません。

更新前に選択を行わないようにする場合は、拡張永続コンテキストを介してエンティティが管理されていない状態に到達しないようにする必要があります(マージを防ぐため)。エンティティが複数のユーザーによって頻繁に更新される可能性がある場合、DBに移動するよりも一貫性の管理に時間がかかるため、キャッシュのパフォーマンスが低下する可能性があります。

そこでパフォーマンスのボトルネックが発生した場合は、最初に関連するエンティティのフェッチと伝播のアノテーションを確認する必要があります。それらが大きすぎる場合は、リクエストを行ったり、DBとの間で大量のデータを更新したりします。

于 2012-07-31T16:21:39.690 に答える
1

https://community.jboss.org/message/751275#751275にクロス投稿-そこで私の回答を参照してください。

于 2012-08-20T11:00:23.460 に答える