目前,我们的 Infinispan 二级缓存存在一些问题。我们准备了两个测试用例:
1) 新创建的对象不放在二级缓存中。我们在第一个事务中创建一个新对象(TestEntity)。我们看到它没有放在二级缓存中,即使我们刷新它。当我们关闭事务(容器管理)并创建第二个事务时,新创建的对象仍然没有在二级缓存中找到,但是如果我们加载它,我们会在数据库中找到它。所以我们确信它是在第一个事务中创建和提交的。但是为什么第一个事务关闭后新创建的对象没有放入二级缓存呢?
2)刷新后从二级缓存中删除更新的对象我们正在从数据库中加载一个实体,因此它在二级缓存中。现在我们正在更新这个加载实体的属性并进行刷新。如果我们再次检查二级缓存,实体不再被缓存。为什么在更新 + 刷新后它会从缓存中删除,我们如何防止这种情况发生?
案例一:代码:
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));
}
}
日志输出第一笔交易:
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
日志输出第二个事务:
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:准备:预加载实体“TMP0000000000043”,它已经在数据库中
代码:
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 - 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>
启用二级缓存:
<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)