-->
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.  [ 3 posts ] 
Author Message
 Post subject: Mutliple collections fetching creates cartesian product?
PostPosted: Tue Oct 16, 2007 9:45 am 
Regular
Regular

Joined: Thu Oct 13, 2005 4:19 am
Posts: 98
Say I want to fetch a person with all his sons and daughters from the database:
"select p from Person p left join fetch p.sons left join fetch p.daughters where p.id = 5"
Person has the properties Set<Son> sons and Set<Daughter> daughters.

If person with id 5 has 7 sons and 3 daughters, the select generates resultset of 21 rows, which is the cartesian product 7 times 3.

For a person with 20 sons and 10 daughters, this generates 400 rows, which is starting to scare me for performance reasons.

I need all sons and daughters to be eagerily fetched: directly after the query I am closing the persistence context (hibernate session) and serializing it. I process the person and his sons and daughters in a client.

How can I avoid the cartesian product?

_________________
http://www.ohloh.net/accounts/ge0ffrey


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 16, 2007 1:07 pm 
Regular
Regular

Joined: Mon Aug 07, 2006 6:22 pm
Posts: 67
I believe the simple answer is to use subselects, with eager fetching.

In your mapping config for each of the "sons" and "daughters" sets, add attributes lazy="false" and fetch="subselect". Then, you should be able to simplify your query to "from Person p where p.id = 5". It should eagerly fetch the sets, with subselects instead of joins.

To see what SQL it's generating, turn on SQL logging by turning on the following properties:

* hibernate.show_sql
* hibernate.format_sql
* hibernate.use_sql_comments


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 17, 2007 4:34 am 
Regular
Regular

Joined: Thu Oct 13, 2005 4:19 am
Posts: 98
Thanks, that would cut it, but it turns out I also need to eager fetch a toOne property of Son and Daughter, for example son.favoriteGiJoe and daughter.favoriteDoll

Using Hibernate.initialize(p.getSons()) and Hibernate.initialize(p.getDaughters()) won't initialize son.favoriteGiJoe and daughter.favoriteDoll

I don't suppose it's possible to write a query like this:

select p from Person p
left join subselect p.sons s
left join fetch s.favoriteGiJoe
left join subselect p.daughters d
left join fetch d.favoriteDoll

This way I 'd avoid the n+1 query problem and the cartesian product problem, as hibernate could figure out to do 3 queries:
- one for person
- one for the sons and their favorite GiJoe
- one for the daughters and their favorite Doll

_________________
http://www.ohloh.net/accounts/ge0ffrey


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