Objects are not added to the cache or removed after an update
nate.h Apr 15, 2013 3:45 PMWe currently have some problems with our Infinispan 2nd level cache. We've prepared two test cases:
1) Newly created objects are not put in the 2nd level Cache.
We create a new object (TestEntity) in a first transaction. We see that it is not put in the 2nd level cache, even if we flush it. When we close the transaction (container managed) and create a second transaction, the newly created object still isn't found in the 2nd level cache, but if we load it we find it in the database. So we are sure that it is created and committed in the first transaction. But why isn't the newly created object put into the 2nd level cache after the first transaction is closed?
2) updated objects are removed from the 2nd level cache after flush
We are loading an entity from the database, so it is in the 2nd level cache. Now we are updating an attribute of this loaded entity and do a flush. If we check the 2nd level cache again, the entity is not cached anymore. Why is it removed from the cache after updating + flushing and how can we prevent this?
Case 1:
Code:
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)); } }
Log output 1nd Transaction:
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
Log output 2nd Transaction:
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!
Case 2:
Preparation: PreLoad of entity "TMP0000000000043" which is already in DB
Code:
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"));
Log output:
17:21:17,685 INFO [stdout] (default-threads - 6) LifecycleEngine TestEntity : true
17:21:17,857 INFO [stdout] (default-threads - 6) LifecycleEngine TestEntity : false
We are using the following setup:
- EAP-6.0.1
- Hibernate 4.2
- Infinispan as provided by EAP-6.0.1 as 2nd level cache
Subsystem configuration:
<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>
Enabling of level 2 cache:
<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"/>
The annotations on the entities are :
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)