Hibernate Caching (EhCache)
I have an application using Hibernate and ehcache.
Problem is I am not able to retrieve all elements from the cache as expected.
First my configuration:
Code:
SessionFactory from spring-config:
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
</props>
</property>
From ehcache.xml:
Code:
<cache
name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600" logging="true" statistics="true" >
</cache>
My java-classes simplified for clarity:
Code:
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE , region="EnhetCache")
public class Enhet{
@OneToMany(mappedBy = "tjenesteeier")
@Cascade(ALL)
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE, region = "TjenesteKatalogCollectionCache")
private List<Tjenestekatalog> tjenestekataloger;
//...
} //end class Enhet
@Entity
@PrimaryKeyJoinColumn(name = "ORELEMENT")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "TjenesteKatalogCache")
public class Tjenestekatalog{
@OneToMany(mappedBy = "tjenestekatalog")
@Cascade(ALL)
@Cache(usage= CacheConcurrencyStrategy.READ_WRITE, region = "SkjemaListCache")
private List<Skjema> skjemaer;
//....
} //end class Tjenestekatalog
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="SkjemaCache")
@PrimaryKeyJoinColumn(name = "ORELEMENT", referencedColumnName = "ID")
public class Skjema extends ORElement {
//...
//...
//...
}
My JUnit-test:
Code:
@Test
public void testQueryCache() throws SQLException, DatabaseUnitException, IOException {
runQuery();
session.clear();
session.close();
session = sessionFactory.openSession();
runQuery();
}//end testQueryCache
private void runQuery(){
log.debug("\n\n ******* Running Query ***************");
//printCacheContents();
List<Enhet> enheter = session.createQuery("From Enhet").setCacheable(true).list();
for(Enhet enhet : enheter) {
log.debug("Enhet found: " + enhet.getOrganisasjonsnummer());
List<Tjenestekatalog> kataloger = session
.createQuery("select tjenestekataloger From Enhet e where e.organisasjonsnummer = :orgnr")
.setCacheable(true)
.setParameter("orgnr", enhet.getOrganisasjonsnummer())
.list());
for (Tjenestekatalog katalog : kataloger) {
assertNotNull(katalog);
List<Skjema> skjemaer = session.createQuery("select skjemaer from Tjenestekatalog t where t.id = :id")
.setCacheable(true)
.setParameter("id", katalog.getId())
.list();
for (Skjema skjema : skjemaer) {
log.debug("SkjemaId: " + skjema.getId());
}
}
}
//printCacheContents();
}//end runQuery
private void printCacheContents(){
boolean contains = session.getSessionFactory().getCache().containsEntity(Skjema.class,4001);
log.debug("cache contains skjema (4001): " + contains);
contains = session.getSessionFactory().getCache().containsEntity(Skjema.class,4002);
log.debug("cache contains skjema (4002): " + contains);
contains = session.getSessionFactory().getCache().containsEntity(Enhet.class,1001);
log.debug("cache contains enhet: " + contains);
contains = session.getSessionFactory().getCache().containsEntity(Tjenestekatalog.class,2001);
log.debug("cache contains katalog: " + contains);
log.debug("HitCount: " + session.getSessionFactory().getStatistics().getSecondLevelCacheHitCount());
log.debug("QC Hits: " + session.getSessionFactory().getStatistics().getQueryCacheHitCount());
for(String q : session.getSessionFactory().getStatistics().getQueries()) {
log.debug("\t\t" + q);
}
}
}
As you can see from my test I run the queries once, close the session and start a new one before running the exact same queries again.
This should result in queryCache hits for the last set of queries, from what I can understand.
The problem is however, that my assert in the runQuery-method fails at the second time the queries are executed. This means that I can successfully retrieve
the data from the database, data gets inserted into my 2L cache, but when I try again using a new session it is zero.
The List<Tjenestekatalog> itself is not null, and it also has one value, which is null.
According to the ouput in my printCacheContents-method all objects are present in the cache.
And also the sql-queries are put as keys in my QueryCache.
StandardQueryCache []: Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache
EhcacheGeneralDataRegion []: key: sql: select tjenesteka1_.O [....]What am I doing wrong? This has been giving me a headache for days, so I hope someone can help.
Thanks in advance.