I've recently had issues with performance with getting a list of Objects which has as one of it's properties a Set of other objects. Essentially, our Banner class has a Set of bannerClickHistory objects which is a one-to-many mapping. When i go and grab a list of banners, i would also retrieve a set of bannerclickhistory objects. The problem i've encountered, is that over time as the number of rows grows in the Banner table with associated bannerclickhistory, it was taking almost up to 5 minutes to grab a collection of even 100 banner objects. I've turned on the show_sql = true flag, and now have noticed that the Hibernate SQL seems to generate an HSQL statement for getting the bannerclickhistory for every banner object (parent) that is fetched (resulting in 99 additional child calls). I thought that setting the fetch="join" in the parent .hbm file would do the trick to narrow down the number of queries by doing a join but it doesn't seem to do what i was exepecting. Is there something I'm missing or is my interpretation of this fetch="join" not correct? Thanks for any help. I have a sample of the mapping file and the execution code down below.
Hibernate version: 3.2.0
Name and version of the database you are using: Postgres 7.4
Mapping file for the banner
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 10-Aug-2006 12:24:19 PM by Hibernate Tools 3.2.0.beta6a -->
<hibernate-mapping>
<class name="com.gdi.mms.businessobjects.Banner" table="banner">
<id name="id" type="int">
<column name="bannerkey" />
<generator class="sequence">
<param name="sequence">banner_id_seq</param>
</generator>
</id>
<property name="licenseeid" type="int">
<column name="licenseekey" not-null="true" />
</property>
<set name="bannerClickHistory" inverse="true" lazy="false" fetch="select">
<key>
<column name="BannerKey" not-null="true" />
</key>
<one-to-many class="com.gdi.mms.businessobjects.BannerClickHistory" />
</set>
</class>
</hibernate-mapping>
java code making the call, the call ends up querying for 3 Banner items in the list... and the HSQL shows that 3 calls were made to the bannerClickHistory for each banner. (this is the part where i'm wondering how do you join if even possible)Code:
System.out.println("starting now....");
long startTime = System.currentTimeMillis();
tx = session.getTransaction();
tx.begin();
Query query = session.createQuery("from Banner where licenseeid = 445");
resultList = query.list();
tx.commit();
long endTime = System.currentTimeMillis();
System.out.println("All done getting banner list size of : " + resultList.size());
System.out.println("Execution time for this is: " + (endTime - startTime));
The HSQL outputCode:
starting now....
Hibernate: select banner0_.bannerkey as bannerkey19_, banner0_.licenseekey as licensee2_19_ from banner banner0_ where banner0_.licenseekey=445
Hibernate: select bannerclic0_.BannerKey as BannerKey1_, bannerclic0_.bannerclickhistorykey as bannercl1_1_, bannerclic0_.bannerclickhistorykey as bannercl1_22_0_, bannerclic0_.BannerKey as BannerKey22_0_, bannerclic0_.CreationDate as Creation3_22_0_ from BannerClickHistory bannerclic0_ where bannerclic0_.BannerKey=?
Hibernate: select bannerclic0_.BannerKey as BannerKey1_, bannerclic0_.bannerclickhistorykey as bannercl1_1_, bannerclic0_.bannerclickhistorykey as bannercl1_22_0_, bannerclic0_.BannerKey as BannerKey22_0_, bannerclic0_.CreationDate as Creation3_22_0_ from BannerClickHistory bannerclic0_ where bannerclic0_.BannerKey=?
Hibernate: select bannerclic0_.BannerKey as BannerKey1_, bannerclic0_.bannerclickhistorykey as bannercl1_1_, bannerclic0_.bannerclickhistorykey as bannercl1_22_0_, bannerclic0_.BannerKey as BannerKey22_0_, bannerclic0_.CreationDate as Creation3_22_0_ from BannerClickHistory bannerclic0_ where bannerclic0_.BannerKey=?
All done getting banner list size of : 3
Execution time for this is: 360