We have an LazyInitializationException on a OneToMany association
only when local query and 2nd level entity cache is enabled. When local query cache is disabled, the exception goes away. Initializing the collection in the session also makes the LIE not happen. We are using, see below, a named query to custom join the association and expect this to achieve the eager loading for this case. I've confirmed the entities, and it's associations are in the 2nd level cache. Essentially, the collections are dirty when coming from the cache, and initialized when not coming from the cache.
Is there a way to resolve this error using named queries without having to resort to initializing the collection on the entity?
We are using Hibernate 3.3.1.GA and JbossCache 3.1.0.GA Cascabel, on Jboss-5.1.0.GA. Thanks for any assistance.
persistence.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="core" transaction-type="JTA">
<jta-data-source>java:/mysql-pss2-ds</jta-data-source>
<class>EntityA</class>
<properties>
<!--
Defaults are now located in
jboss_dir/server/default/deployers/ejb3.deployer/META-INF/jpa-deployers-jboss-beans.xml
ONLY add properties here to override defaults
-->
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect"/> <property
name="hibernate.show_sql" value="false"/> <property
name="hibernate.format_sql" value="false"/> <property
name="hibernate.hbm2ddl.auto" value="validate"/> <property
name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.region.factory_class"
value="org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory"/>
<property name="hibernate.cache.region.jbc2.cachefactory"
value="java:CacheManager"/> <property
name="hibernate.cache.region.jbc2.cfg.entity" value="mvcc-entity"/>
<property name="hibernate.cache.region.jbc2.cfg.query"
value="local-query"/> <property name="hibernate.cache.region_prefix"
value="core"/>
</properties>
</persistence-unit>
</persistence>
The entity
Code:
@Entity
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
@Table(name = "entityA",uniqueConstraints = {@UniqueConstraint(columnNames={"entityAName", "client"})})
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@NamedQueries( {
@NamedQuery(name = "EntityA.findByNameAndClientLJF.Single",
query = "select distinct(p) from EntityA p left join fetch p.entityBCollection "
+ "left join fetch p.entityC where p.entityAName = :name and p.client = :client",
hints = { @QueryHint(name = "org.hibernate.cacheable",
value = "true") }) })
public class EntityA {
@Cache (usage=CacheConcurrencyStrategy.TRANSACTIONAL)
@OneToMany(fetch = FetchType.LAZY, mappedBy = "entityA")
private Set<EntityB> entityBs = new HashSet<EntityB>();
public Set<EntityB> getEntityBs() {
return entityBs;
}
public void setEntityBs(Set<EntityB> entityBs) {
this.entityBs = entityBs;
}
}
The eaobean finder
Code:
public EntityA findByNameAndClientLJF(java.lang.String name, boolean client) {
Query q = em.createNamedQuery( "EntityA.findByNameAndClientLJF.Single" );
q.setParameter("name", name);
q.setParameter("client", client);
List<EntityA> val = q.getResultList();
if(val.isEmpty()) {
return null;
} else if (val.size() == 1) {
return val.get(0);
} else {
throw new NonUniqueResultException(q.toString());
}
}
The entity A manager
Code:
public EntityA getEntityA(String name, boolean isClient) {
try {
return entityAEAO.findByNameAndClientLJF(name, isClient);
} catch(NoResultException nre) {
return null;
}
}
The remote web accessor that triggers the errors
Code:
private boolean checkEntityBs(String name) {
boolean x = false;
// check
EntityAManager eManager = EJBFactory
.getBean(EntityAManager.class);
if (!eManager.getEntityA(name).getEntityBs()
.isEmpty()) {
//LazyInitializationException occurs here.
x = true;
}
return x;
}