現在、Infinispan の第 2 レベルのキャッシュに問題があります。2 つのテスト ケースを用意しました。
1) 新しく作成されたオブジェクトは、第 2 レベルのキャッシュに置かれません。最初のトランザクションで新しいオブジェクト (TestEntity) を作成します。フラッシュしても、第 2 レベルのキャッシュに格納されていないことがわかります。トランザクション (コンテナー管理) を閉じて 2 番目のトランザクションを作成すると、新しく作成されたオブジェクトはまだ 2 次キャッシュに見つかりませんが、それをロードするとデータベースに見つかります。したがって、最初のトランザクションで作成およびコミットされていることが確実です。しかし、最初のトランザクションが閉じられた後、新しく作成されたオブジェクトが第 2 レベルのキャッシュに入れられないのはなぜでしょうか?
2) 更新されたオブジェクトは、フラッシュ後に第 2 レベルのキャッシュから削除されます。データベースからエンティティをロードしているため、エンティティは第 2 レベルのキャッシュにあります。ここで、このロードされたエンティティの属性を更新し、フラッシュを実行します。2 番目のレベルのキャッシュを再度確認すると、エンティティはもうキャッシュされていません。更新 + フラッシュ後にキャッシュから削除されるのはなぜですか? また、これを防ぐにはどうすればよいですか?
ケース 1: コード:
private static String tmpInsId = " ";
public void onMessages(final Message[] messageBulk) {
boolean isInCache = this.entityManager.getEntityManagerFactory().getCache().contains(TestEntity.class, tmpInsId);
System.out.println("+++++ new TestEntity (" + tmpInsId + "): " + isInCache);
if (!isInCache) {
final TestEntity ri = this.entityManager.find(TestEntity.class, tmpInsId);
if (ri != null) {
System.out.println("+++++ new TestEntity (" + tmpInsId + "): Loaded!");
isInCache = this.entityManager.getEntityManagerFactory().getCache().contains(TestEntity.class, tmpInsId);
if (!isInCache) {
System.out.println("+++++ new TestEntity (" + tmpInsId + "): Not in cache!"); // shouldn't be possible
}
else {
System.out.println("+++++ new TestEntity (" + tmpInsId + "): Cached!");
}
}
else {
tmpInsId = ("TMP" + String.valueOf(System.currentTimeMillis()) + "0000000000").substring(0, 16);
final TestEntity tmp = new TestEntity(tmpInsId, 0L, "N", "N", new Date());
this.entityManager.persist(tmp);
System.out.println("+++++ new TestEntity (" + tmpInsId + "): "
+ this.entityManager.getEntityManagerFactory().getCache().contains(TestEntity.class, tmpInsId));
this.entityManager.flush();
System.out.println("+++++ new TestEntity (" + tmpInsId + "): "
+ this.entityManager.getEntityManagerFactory().getCache().contains(TestEntity.class, tmpInsId));
this.entityManager.find(TestEntity.class, tmpInsId);
System.out.println("+++++ new TestEntity (" + tmpInsId + "): "
+ this.entityManager.getEntityManagerFactory().getCache().contains(TestEntity.class, tmpInsId));
}
}
ログ出力 1 番目のトランザクション:
17:54:30,730 INFO [stdout] (default-threads - 2) +++++ new TestEntity ( ): false
17:54:30,745 INFO [stdout] (default-threads - 2) +++++ new TestEntity (TMP1366041270730): false
17:54:30,761 INFO [stdout] (default-threads - 2) +++++ new TestEntity (TMP1366041270730): false
17:54:30,761 INFO [stdout] (default-threads - 2) +++++ new TestEntity (TMP1366041270730): false
ログ出力 2 番目のトランザクション:
17:55:00,058 INFO [stdout] (default-threads - 2) +++++ new TestEntity (TMP1366041270730): false
17:55:00,058 INFO [stdout] (default-threads - 2) +++++ new TestEntity (TMP1366041270730): Loaded!
17:55:00,058 INFO [stdout] (default-threads - 2) +++++ new TestEntity (TMP1366041270730): Cached!
ケース 2: 準備: 既に DB にあるエンティティ "TMP0000000000043" の PreLoad
コード:
System.out.println(" TestEntity : " + this.entityManager.getEntityManagerFactory().getCache().contains(TestEntity.class, "TMP0000000000043"));
testEntity().setLstUpdTmstmp(currentTimestamp);
this.entityManager.flush();
System.out.println(" TestEntity : " + this.entityManager.getEntityManagerFactory().getCache().contains(TestEntity.class, "TMP0000000000043"));
ログ出力: 17:21:17,685 INFO [stdout] (default-threads - 6) LifecycleEngine TestEntity : true 17:21:17,857 INFO [stdout] (default-threads - 6) LifecycleEngine TestEntity : false 次のセットアップを使用しています。 - EAP-6.0.1 - Hibernate 4.2 - 第 2 レベルのキャッシュとして EAP-6.0.1 によって提供される Infinispan
サブシステム構成:
<subsystem xmlns="urn:jboss:domain:infinispan:1.3">
<cache-container name="hibernate" default-cache="local-query" module="org.jboss.as.jpa.hibernate:4">
<local-cache name="entity">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="local-query">
<transaction mode="NONE"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<local-cache name="timestamps">
<transaction mode="NONE"/>
<eviction strategy="NONE"/>
</local-cache>
</cache-container>
</subsystem>
レベル 2 キャッシュの有効化:
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE" />
<property name="hibernate.cache.default_cache_concurrency_strategy" value="transactional" <property
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
エンティティの注釈は次のとおりです。
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)