-->
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.  [ 5 posts ] 
Author Message
 Post subject: Fetch Joining problem
PostPosted: Wed Sep 22, 2004 9:33 am 
Senior
Senior

Joined: Sun Oct 26, 2003 5:05 am
Posts: 139
I'm having a pretty serious fetch joining problem. I've went back to an older application that I wrote a long time ago. It's not a mess, but my Hibernate skills were not nearly as competent as they are now. Anyhow, fetch joining with collections doesn't seem to work correctly on this project as it does on others, and I'm having trouble figuring out what could be the problem :/

Basically Hibernate is returning duplicates of the object I'm selecting for each element that it fetch joins. So if I have object X with 3 Y as children, the query will return a list of 3 X's. This is not what I would expect since I have done left join fetch on many queries on other projects.

I guess my question is how can this happen? I'm upgraded the hibernate2.jar to the latest version and I'm using the same database (postgres 7.5) as the other projects where fetch joining is working just fine. Here is a simple example:

Code:
Query query = session.createQuery(
   "select page " +
   "from Page page " +
   "   left join fetch page.children child " +
   "order by page.name"
);

return query.list();


As you can this, query is simple. If I take off lazy loading for page.children and remove the left join fetch, the query will return 47 results in my case (correct number). However, if I run this query with lazy-load="true" and put back in the left join fetch, the query returns 80 results, so 33 are duplicates. As an example, I did a system out for each Page in the list returned by this query, printing page.name and it's number of children. The objects with the same name also have the same Id. Here is what happens:

Code:
administrative-monetary-penalty 0
association-news 0
automated-commercial-environment 0
border-smart-driver-seminar 0
canada-customs-links 0
community 0
company 4
company 4
company 4
company 4
company-overview 0
compliance-verification 0
contact 2
contact 2
contact-request-form 0
crossing-borders-for-a-new-era 0
customer-testimonials 0
customs-automated-forms-entry-system 0
customs-news 0
customs-program-management 0
customs-self-assessment--csa--for-carriers 0
customs-self-assessment-for-importers 0
customs-solutions 3
customs-solutions 3
customs-solutions 3
customs-trade-partnership-against-terrorism 0
directions 0
driver-training-dvd 0
editorial-page 0
events 0
forms-and-labels-printing 0
free-and-secure-trade 0
import-and-export-services 0
importing-to-canada-101-and-exporting-from-canada-101 0
index 5
index 5
index 5
index 5
index 5
industry-links 0
news-and-events 4
news-and-events 4
news-and-events 4
news-and-events 4
online-rns 0
partners-in-protection 0
pre-arrival-processing-system 0
privacy-policy 0
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
quicklinks 12
seminars 5
seminars 5
seminars 5
seminars 5
seminars 5
senior-management-team 0
service-solutions 4
service-solutions 4
service-solutions 4
service-solutions 4
shipping-to-canada-101 0
smart-border-carrier-dvd 0
technology-solutions 1
terms-and-use 0
training-dvds 2
training-dvds 2
training-solutions 2
training-solutions 2
us-and-canada-customs-related-agency-links 0
verification-and-audit-seminar-101 0


So as you can see, the children are being mapped by hibernate just fine. This is quite frankly baffling me. Anyway, here is the mapping. I've removed a lot of properties and other sets to make this beast easier to read. I assure you that even if I take out the other mappings just to get it to work, the problem still happens.

Code:
   <class name="com.upfactor.cms.domain.website.Page" table="page">
      <cache usage="read-write" />
      <id name="id" column="id" type="long" unsaved-value="0">
         <generator class="sequence">
            <param name="sequence">page_id_seq</param>
         </generator>
      </id>
      <many-to-one name="parent" column="parentPageId" class="com.upfactor.cms.domain.website.Page" cascade="none" />

      <property name="name" column="name"/>
        <property name="headerName" column="headerName"/>

      <set name="children" table="page" order-by="name"
         cascade="delete-orphan" lazy="true" outer-join="true">
         <cache usage="read-write" />
         <key column="parentPageId"/>
         <one-to-many class="com.upfactor.cms.domain.website.Page"/>
      </set>
   </class>


Anyway, I'd appreciate any advice. THe only thing that I can think up right now is that since the children are the same type as the parent, perhaps Hibernate isn't handling it properly.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 22, 2004 9:45 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
This is normal, Hibernate does not make the results unique. You will have to do that yourself (drop them all in a HashSet for example)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 22, 2004 10:32 am 
Senior
Senior

Joined: Sun Oct 26, 2003 5:05 am
Posts: 139
Are you sure? I've done fetch joining like this, with backed test cases, and I've never had this problem. To me, fetch joining behaved exactly as doing lazy-loading or not making the collections lazy at all.

I did wrap the list in a HashSet and it removed the duplicates, but I don't understand why this has to be done. Isn't this a big waste of memory in building 33 objects with unique children set references? I guess 33 objects isn't a lot, but I'm detecting a scalability problem unless it's handled very efficiantly inside Hibernate. Even still, clients to the code I'm modifying expect a List, not Set and this will cause some problems unless I convert the Set back into a list. Sigh..

Are you sure I can't just tell Hibernate to do this for me with the hope that it can do a better job at optimizing it than I can?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 22, 2004 10:41 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Um. It is not 33 objects, it is 33 references to the same object. Basically, there is no reason why Hibernate can do this unique-ification any more efficiently than you can do it.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 22, 2004 11:56 am 
Senior
Senior

Joined: Sun Oct 26, 2003 5:05 am
Posts: 139
I realize it's references, but the children are still sets of references (which may be the same ones or different ones, but as a Hibernate user, I don't know how it does that).

Regardless, the only way I can quickly fix this problem is by wrapping the query.list() in a HashSet, then re-wrapping it in an ArrayList (to avoid changing the interface since many clients will break).

I guess this just hasn't come up for me, ever. That's strange because I really have been doing fetch joins a lot and have not even noticed this (and I make the effort so that my test data in dbunit is quite realistic).

So there is no way for Hibernate to just drop the duplicates outside of what I'm doing?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.