-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Using Fetch In HQL
PostPosted: Wed Sep 17, 2003 2:44 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2003 9:11 pm
Posts: 32
I looked around thinking this is answered somewhere but didn't find anything......

I'm using Hibernate 2.0.2. I'm creating the following HQL:

Code:
List ads = session.createQuery("select distinct ad from com.itsolut.entity.tracker.Ad as ad " +
                                     " left join fetch ad.redirects").list();


In the database to test, I have two Ads and 3 Redirects.
A1 links to R1 & R2
A2 links to R3

When I issue the above query A1 is returned twice (once for each Redirect record). Is this the expected functionality with the fetch keyword?

Because when I remove the fetch keyword, the query return A1 once liked I expected. Except now I have to manually initialize the collection before returing to the view....

Here are the mappings:
Code:
<class name="com.itsolut.entity.tracker.Ad" table="ad">
      <id name="adID" type="long" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <property name="companyID" type="int" not-null="true"/>

      <property name="creation" type="timestamp"/>
      <property name="start" type="date"/>
      <property name="stop" type="date"/>

      <property name="name" type="string"/>

      <many-to-one name="lastRedirect" class="com.itsolut.entity.tracker.Redirect"/>
      <set name="redirects" lazy="true" cascade="save-update">
         <key column="adID"/>
         <one-to-many class="com.itsolut.entity.tracker.Redirect"/>
      </set>

   </class>

   <class name="com.itsolut.entity.tracker.Redirect" table="redirect">
      <id name="redirectID" type="long" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <property name="url" type="string"/>
      <property name="creation" type="timestamp"/>

      <property name="clicks" type="int"/>
      <property name="sales" type="int"/>
      <property name="revisit" type="int"/>
      <property name="saleMoney" type="com.itsolut.core.hibernate.type.MoneyType">
         <column name="saleAmount"/>
         <column name="saleCurrency"/>
      </property>

      <property name="active" type="boolean"/>
      <many-to-one name="ad" column="adID" class="com.itsolut.entity.tracker.Ad"/>
   </class>


Top
 Profile  
 
 Post subject: Same problem
PostPosted: Thu Sep 25, 2003 7:46 am 
Newbie

Joined: Thu Sep 25, 2003 7:28 am
Posts: 1
I've got the same problem in my tests. The insert of "FETCH" in join alter the generated query to fetch the related tables, that's ok, but in the generated query also the related table appear in the SELECT clause altering the DISTINCT semantics (actualy negating the distinct).
Is that behavor forced by the necessity of traverse the related table ?
may be a bug ?
or there's something we miss ?

Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2003 9:57 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
This is known and intended behaviour (though contraversial). Applying DISTINCT in memory can be a quite expensive operation, so we prefer to leave it to the application. Just add the query results to a hashset and you will be fine....


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2003 10:58 am 
Beginner
Beginner

Joined: Tue Sep 09, 2003 9:11 pm
Posts: 32
Quote:
This is known and intended behaviour (though contraversial). Applying DISTINCT in memory can be a quite expensive operation, so we prefer to leave it to the application. Just add the query results to a hashset and you will be fine....


hmmm... Ok, thanks for the heads up. I couldn't find the discussion around FETCH in the archive; but I can understand the controversial nature. This should probably go into the documentation [in big bold letters :)] or at least become an FAQ....


Thanks for the answer,
Chris....[/quote]


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2003 11:00 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Note that another reason for this decision is that we prefer that if we call setMaxRows(100), then that limits the results to exactly 100 rows!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2003 1:36 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2003 9:11 pm
Posts: 32
let me get this straight.....

that would be 100 rows including the collection records and not 100 rows of the parent object.

So if I had 200 object As and each had 2 object Bs in a collection then only 50 objects As would be returned?
50 As
100 Bs

I understand where you coming from, however, it's just not intuitive at all. So if I really wanted to return 100 As than I should not use FETCH in the query. I should probably run each A.getCollectionB() through Hibernate.initialize().

Is there another way to initialize all of the Bs for a set of As? Just trying to cut down on the number of queries. In my initialize example, there will be 101 queries executed (1 for A, 100 for B).

Chris....


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2003 3:56 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Dude, this is a limitation of SQL and the JDBC API. I cannot possibly provide any way to limit the number of actual instances of the parent returned! Think about it ;)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2003 5:09 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2003 9:11 pm
Posts: 32
Sorry, not exactly what I was asking. I understand the SQL LIMIT limitations. Given the implementation of FETCH, I was thinking outloud about how to best retrieve objects.

I have most of my children collections marked to lazy load since I need them only infrequently depending on the function being executed.

Also, this particular function is passing data back to the view layer after the session is closed and therefore lazy loading is not available.

Right now, I'm iterating through each parent object and calling Hibernate.initialize() for each child collection (hence 1 SQL call per parent object to retrieve the collection).

What I am trying to figure out (and tried to ask) is how to minimize the number of SQL queries generated.

I was wondering if there is a way to quickly retrieve all of the collection sub-objects in one query. For example, could I issue an HQL query that did something like "select b from B where b.parentID in(......)". This HQL would return all of the child objects. I would do this just to get them into the session cache.

Then if I call Hibernate.initialize() for each parent.collection, the children are loaded into the session cache. Now the question is, does Hibernate.initalize() code path use the Session cache to retrieve objects or is a SQL call still generated.

hmmm.... sounds like I'll just go play a bit and see what actually happens...

Chris....


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 25, 2003 5:27 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
If you enable batch loading for the collection then of course the collections are loaded by batch.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.