When using the second level cache, in our case EHCache, we do not want proxies for entities or collections to be cached. So, in this case we specify :
Code:
<cache include="non-lazy" usage="nonstrict-read-write">
Is this sufficient or are we missing something? The entities in question are all proxied and have default lazy="true" which is the behavior we desire when working with the first level cache.
On a side note, the reason why we require this behavior is because we are getting LazyInitializationExceptions at times when accessing the second level cache from new sessions. (We utilize Open Session In View pattern). We'd like to beef up performance, but this is a bit of a showstopper and we'd rather not lock entities to new sessions in ad hoc fashion. Rational?
Sample below:
Hibernate version: 3.1.2
Mapping documents: Organization Code:
<hibernate-mapping>
<class proxy="com.casebank.spotlight.domain.Organization" table="organization" name="com.casebank.spotlight.domain.Organization">
<bag inverse="true" cascade="none" fetch="subselect" lazy="true" table="organization_relation" name="toOrganizationRelations">
<cache include='non-lazy' usage="nonstrict-read-write"/>
<key column="from_organization_id"/>
<one-to-many class="com.casebank.spotlight.domain.OrganizationRelation"/>
</bag>
</class>
</hibernate-mapping>
Organization Relation Code:
<hibernate-mapping>
<class table="organization_relation" name="com.casebank.spotlight.domain.OrganizationRelation">
<cache include='non-lazy' usage="read-write"/>
<composite-id name="id" class="com.casebank.spotlight.domain.OrganizationRelationKey">
<key-property name="fromOrganizationId" column="from_organization_id"/>
<key-many-to-one name="relationType" column="relation_type_id" class="com.casebank.spotlight.domain.RelationType"/>
<key-many-to-one name="toOrganization" column="to_organization_id" class="com.casebank.spotlight.domain.Organization"/>
</composite-id>
</class>
</hibernate-mapping>
RelationType Code:
<hibernate-mapping>
<class proxy="com.casebank.spotlight.domain.RelationType" table="relation_type" name="com.casebank.spotlight.domain.RelationType">
<cache include='non-lazy' usage="nonstrict-read-write"/>
<id unsaved-value="null" name="id">
<generator class="uuid.hex"/>
</id>
<map cascade="all" fetch="join" lazy="false" table="relation_type_description" name="descriptions">
<key column="relation_type_id"/>
<index type="string" column="locale_id"/>
<element type="string" column="translation"/>
</map>
<map cascade="all" fetch="join" lazy="false" table="relation_type_name" name="names">
<key column="relation_type_id"/>
<index type="string" column="locale_id"/>
<element type="string" column="translation"/>
</map>
<property name="keyCode" column="key_code"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():The following is executed in a private method where the session is guaranteed to be open (we use JTA getCurrentSession() in combination with OpenSessionInView pattern)
Code:
private void eagerlyLoadOrganizationRelations(Session session,
Organization o, List organizationRelationsTypes)
throws HibernateException {
String queryStr = "from Organization as domain "
+ "left join fetch domain.toOrganizationRelations as r "
+ "where domain.id = :domainId";
if (organizationRelationsTypes != null) {
queryStr += " AND r.id.relationType.keyCode "
+ "IN (:relTypesKeyCodes)";
}
Query q = session.createQuery(queryStr);
q.setCacheable(true);
q.setParameter("domainId", (String) o.getId());
if (organizationRelationsTypes != null) {
q.setParameterList("relTypesKeyCodes", organizationRelationsTypes);
}
q.list();
}
Full stack trace of any exception that occurs:Code:
15:43:50,923 ERROR [LazyInitializationException] could not initialize proxy - the owning Session was closed
org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:56)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:98)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:158)
at com.casebank.spotlight.domain.RelationType$$EnhancerByCGLIB$$dd4cda35.equals(<generated>)
at org.hibernate.util.EqualsHelper.equals(EqualsHelper.java:10)
at org.hibernate.type.AbstractType.isEqual(AbstractType.java:108)
at org.hibernate.type.ComponentType.isEqual(ComponentType.java:113)
at org.hibernate.cache.CacheKey.equals(CacheKey.java:51)
at java.util.HashMap.eq(HashMap.java:277)
at java.util.HashMap.removeEntryForKey(HashMap.java:548)
at java.util.LinkedHashMap.addEntry(LinkedHashMap.java:403)
at java.util.HashMap.put(HashMap.java:395)
at net.sf.ehcache.store.MemoryStore.put(MemoryStore.java:177)
at net.sf.ehcache.Cache.put(Cache.java:318)
at org.hibernate.cache.EhCache.put(EhCache.java:153)
at org.hibernate.cache.ReadWriteCache.put(ReadWriteCache.java:159)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:153)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:842)
at org.hibernate.loader.Loader.doQuery(Loader.java:717)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.doList(Loader.java:2145)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029)
at org.hibernate.loader.Loader.list(Loader.java:2024)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:375)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:308)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:153)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1129)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at com.casebank.spotlight.dao.hibernate.HibernateOrganizationDAO.eagerlyLoadOrganizationRelations(HibernateOrganizationDAO.java:1539)
at com.casebank.spotlight.dao.hibernate.HibernateOrganizationDAO.executeEagerlyLoadSettings(HibernateOrganizationDAO.java:193)
at com.casebank.spotlight.dao.hibernate.HibernateOrganizationDAO.loadByPrimaryKey(HibernateOrganizationDAO.java:163)
Name and version of the database you are using:
MS SQL Server 2000