We have a very large system that we have been migrating to Hibernate 3.05. For us, Hibernate 3.05 has given us a significant performance advantage over Hibernate 2.x with its ability to perform multiple (eager) left join fetches of collections within the same hql statement by having lifted the cartesian-product restriction in version 3.05.
Poof! It doesn’t work now. I can not get multiple collections to be eagerly initialized within an hql statement. Here is my test-case with comments. Setup information is at the end of this message.
The test case consists of 3 tables (A, B, C). B and C are child entities of A.
In my DB, Table A has one record. Table B and C each have 2 records with a FKs back to A.
I should be able to eagerly load A and its associated B and C collections using a single hql statement. However, I am unable to achieve this. Instead, 2 SQL statements are being executed as though I was using Hibernate 2.x, instead of the Hibernate 3.05 that I am using.
Code:
Session hibernateSession = …
String hql = "select a from A a" +
" left join fetch a.Bs" +
" left join fetch a.Cs" +
" where a.APK = 1";
Query query = hibernateSession.createQuery(hql); // 1st SQL Excecuted
List results = query.list(); // There are 4 entries here as expected.
A a = (A) results.get(0); // Shouldn’t matter which of the 4 I get.
Set bs = a.getBs();
for (Iterator iterator = bs.iterator(); iterator.hasNext();)
{
B b = (B) iterator.next(); // A 2nd SQL Statement is executed !!! ???
}
Set cs = a.getCs();
for (Iterator iterator = cs.iterator(); iterator.hasNext();)
{
C c = (C) iterator.next(); // No SQL Statement is executed.
}
Appreciatively,
Gregg
Here are the *.hbm.xml and *.java files:
Code:
*** A.hbm.xml ***
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="test.A" table="A">
<id name="APK" column="APK" type="long">
<generator class="edit.services.db.hibernate.KeyGenerator"/>
</id>
<set name="Bs" table="B" inverse="true" cascade="all">
<key column="AFK"/>
<one-to-many class="test.B"/>
</set>
<set name="Cs" table="C" inverse="true" cascade="all">
<key column="AFK"/>
<one-to-many class="test.C"/>
</set>
</class>
</hibernate-mapping>
Code:
*** B.hbm.xml ***
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="test.B" table="B">
<id name="BPK" column="BPK" type="long">
<generator class="edit.services.db.hibernate.KeyGenerator"/>
</id>
<many-to-one
name="A"
column="AFK"
class="test.A"
cascade="none"
/>
</class>
</hibernate-mapping>
Code:
*** C.hbm.xml ***
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="test.C" table="C">
<id name="CPK" column="CPK" type="long">
<generator class="edit.services.db.hibernate.KeyGenerator"/>
</id>
<many-to-one
name="A"
column="AFK"
class="test.A"
cascade="none"
/>
</class>
</hibernate-mapping>
Code:
*** A.java ***
public class A
{
private Long aPK;
private Set bs;
private Set cs;
public A()
{
}
public Set getCs()
{
return cs;
}
public void setCs(Set cs)
{
this.cs = cs;
}
public Set getBs()
{
return bs;
}
public void setBs(Set bs)
{
this.bs = bs;
}
public Long getAPK()
{
return aPK;
}
public void setAPK(Long aPK)
{
this.aPK = aPK;
}
}
Code:
*** B.java ***
public class B
{
private Long bPK;
private A a;
public B()
{
}
public Long getBPK()
{
return bPK;
}
public void setBPK(Long bPK)
{
this.bPK = bPK;
}
public A getA()
{
return a;
}
public void setA(A a)
{
this.a = a;
}
}
Code:
*** C.java ***
public class C
{
private Long cPK;
private A a;
public C()
{
}
public Long getCPK()
{
return cPK;
}
public void setCPK(Long cPK)
{
this.cPK = cPK;
}
public A getA()
{
return a;
}
public void setA(A a)
{
this.a = a;
}
}