Can anyone provide any assistance with the second level cache in hibernate. I am relatively new to this area and I am experiencing some unexpected behaviour.
I am using JBoss AS 5.01 with JBoss cache as follows:
Code:
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory"/>
<property name="hibernate.cache.region.jbc2.cfg.entity" value="mvcc-entity"/>
<property name="hibernate.cache.region.jbc2.cfg.query" value="local-query"/>
...
Before I go any further I know the second level cache and query cache is working as I have viewed the cache contents and regions via the JMX console and also monitor the SQL output from hibernate by configuring log4j as follows:
Code:
log4j.logger.org.hibernate.cache=TRACE
log4j.logger.org.hibernate.SQL=DEBUG
I can see hibernate starting regions and returning results from cache and not executing the SQL.
I have a scenario involving three entities and a query which does not behave the way I thought it would.
Here is a simplified representation of the problem I am having:
Code:
@Entity
@Cache(usage = TRANSACTIONAL, region = "entityA")
EntityA
{
...
@NamedQuery(name = "EntityA.listWithAssociation", query = " SELECT DISTINCT a FROM EntityA a "
+ "LEFT JOIN FETCH a.association", hints =
{
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
@QueryHint(name = "org.hibernate.cacheRegion", value = "entityA")
})
...
@OneToMany(cascade = CascadeType.ALL)
@MapKey(...)
@JoinColumn(...)
@Cache(usage = TRANSACTIONAL, region = "entityA")
private Map<EntityC, EntityB> association;
}
@Entity
@Cache(usage = TRANSACTIONAL, region = "entityB")
EntityB
{
...
}
@Entity
@Cache(usage = TRANSACTIONAL, region = "entityC")
EntityC
{
...
}
As you can see I have three entities (all of which are cachable), a named query (which is cached) and an association from EntityA which is a Map of EntityC's to EntityB's (one to many lazy association which is also marked for caching).
The first time I execute the query everything works as expected.
Here is a log extract:
Code:
INFO org.hibernate.cache.StandardQueryCache - starting query cache at region: appName.entityA
DEBUG org.hibernate.cache.jbc2.query.QueryResultsRegionImpl - Created Region for appName.entityA -- regionPrefix is appName
DEBUG org.hibernate.cache.StandardQueryCache - checking cached query results in region: appName.entityA
DEBUG org.hibernate.cache.StandardQueryCache - query results were not found in cache
DEBUG org.hibernate.SQL - <The named query SQL>
DEBUG org.hibernate.cache.StandardQueryCache - caching query results in region: appName.entityA; timestamp=....
If I now open the JMX console and look at the query cache and entity cache the query results are indeed cached ( i can see the correct id's) and the entity cache has regions for each entity and I can see the state in dehydrated form including the association value mapping.
Now if I re-execute the same query I get this in the logs:
Code:
DEBUG org.hibernate.cache.StandardQueryCache - checking cached query results in region: appName.entityA
DEBUG org.hibernate.cache.StandardQueryCache - Checking query spaces for up-to-dateness: [EntityB, EntityA, EntityC]
DEBUG org.hibernate.cache.StandardQueryCache - returning cached query results
No SQL executes
So far so good. Then...
LazyInitializationException occurs attempting to access entityA.association.
This is where I am confused. The entities are all cached, the query is cached and the association is also cached. I can see all the relevant data in the query cache and entity cache and
no SQL is executing (as expected). Why does hibernate not populate the association in entityA when it re hydrates it?
Perhaps rather interestingly if i mark the association as EAGER fetch OR if I navigate the association in my EJB directly after running the named query the
LazyInitializationException no longer occurs AND NO SQL is run. It appears when we tell it to eager fetch or navigate it realises it is in the cache but when we don't it does not bother to look?
Is this expected behaviour or have I missed something?