-->
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.  [ 8 posts ] 
Author Message
 Post subject: @CollectionOfElements and FetchType.EAGER
PostPosted: Fri Mar 02, 2007 12:02 pm 
Newbie

Joined: Thu Mar 01, 2007 5:02 pm
Posts: 8
I'm seeing something unexpected and I 'd like to determine if I'm doing something wrong, or if there's a logical reason for the behavior. When I map a parent child relationship like so:
Code:
public class ItemA {

    @OneToMany(fetch = FetchType.EAGER)
    private Set<ItemB> itemBs = new HashSet<ItemB>();
...
}

and then retrieve a list of ItemA's with something like
Code:
session.createQuery("from ItemA").list();

everything works as expected. The ItemA's and the child ItemB's are retrieved with one query using a left outer join. Great. That's what I want. However, when I map something similar like:
Code:
public class ItemA {

    @CollectionOfElements(fetch = FetchType.EAGER)
    private Set<String> strings = new HashSet<String>();
...
}

and then retrieve a list of ItemA's using the same statement as above, I get one query to retrieve the ItemA's and then another query for each ItemA retrieved to get the ItemB's, which quickly leads to an n+1 issue with this particular object (a frequently retrieved object where the ItemB's in question are always needed). What's odd though, is that if I retrieve only one ItemA, then a single query is used with a left outer join to retrieve the ItemB's; just as one would expect.

Am I missing a second annotation or attribute that would make the @CollectionOfElements retrieve ItemA's with one query or is there a reason why this is a bad idea with @CollectionOfElements as compared to @OneToMany?

Hibernate version:
Hibernate-core 3.2.2ga
Hibernate-annotations 3.2.1ga

Name and version of the database you are using:
HSQL to reproduce these tests, although the same behavior appears in PostgreSQL.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 07, 2007 8:23 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
I cannot reproduce (I actually reproduce the expected behavior), are you sure your fetch depth is appropriately set up?

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 08, 2007 11:13 am 
Newbie

Joined: Thu Mar 01, 2007 5:02 pm
Posts: 8
emmanuel wrote:
I cannot reproduce (I actually reproduce the expected behavior), are you sure your fetch depth is appropriately set up?

Thanks for the response. Believe it or not, I'm glad to hear that you are seeing the expected behavior. That means I most likely have a configuration setting wrong or am using an annotation incorrectly, but that the root behavior is what one would expect it to be (i.e. all in one query).

I'll try moving my fetch depth up and down however if the fetch depth was incorrectly set, wouldn't that effect the @OneToMany example as well? Regardless, I'll try working with the fetch depth and if I still see the issue, I'll post a test case. It's possible my example above isn't as complete as the real situation where I'm seeing the issue.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 08, 2007 3:24 pm 
Newbie

Joined: Thu Mar 01, 2007 5:02 pm
Posts: 8
I'd like to confirm something.

I may have confused myself with all of my testing. I've written some standalone test cases now and I'm seeing @OneToMany and @CollectionOfElements behave consistently with each other, however it still wasn't quite what I expected.

Using:
- @OneToMany or @CollectionOfElements
- FetchType.EAGER
- Session.load()
This works entirely as expected. A single query is used to retrieve the requested object and a left outer join is used to retrieve the child objects.

Using:
- @OneToMany or @CollectionOfElements
- FetchType.EAGER
- Session.createQuery("from object").list()
This did not work quite as I expected it but the more I think about it, my expectations may have been a little off. The list of objects is retrieved using n+1 queries.

Using:
- @OneToMany or @CollectionOfElements
- FetchType.EAGER
- Session.createQuery("from object left join fetch childObjects")
Works as expected. A single query is used to retrieve the entire list of requested objects and a left outer join is used to retrieve the child objects.

I guess my mistake was in assuming that setting (fetch = FetchType.EAGER) would produce outer joins to retrieve the child objects regardless of whether or not I was retrieving one or many of the annotated objects. I'm sure there is a logical reason for the behavior that I'm seeing; mostly likely because of the potential size of a resultset when retrieving a list of objects and their associated children through outer joins.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 08, 2007 7:19 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
HQL queries are not affected by the fetching strategy at all.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 08, 2007 9:48 pm 
Newbie

Joined: Thu Mar 01, 2007 5:02 pm
Posts: 8
emmanuel wrote:
HQL queries are not affected by the fetching strategy at all.

They appear to have some effect. An annotation of:
Code:
public class ItemA{
    ....
    @CollectionOfElements(fetch = FetchType.EAGER)
    private Set<String> strings = new HashSet<String>();
}

used with Session.createQuery("from ItemA").list() causes 1+n queries to retrieve the ItemA's along with all of their child objects whereas:
Code:
public class ItemA{
    ....
    @CollectionOfElements
    private Set<String> strings = new HashSet<String>();
}

and the same Session.createQuery("from ItemA").list() command just creates a single SQL query to retrieve the ItemA's.

Regardless, I appreciate the comments. After you confirmed that you couldn't recreate the original issue I found the flaw in my tests and I now have a better idea of the different SQL that is used with certain annotation and query combinations.

Of course, I'm now having a different problem (duplicate results in my returned List of ItemA's) but I'll try to work out or search for the solution myself before posting here for a answer. Thanks for you help, emmanuel.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 13, 2007 6:41 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
As I said, it has no effect, the EAGER is ignored :-)

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: @CollectionOfElements and FetchType.EAGER
PostPosted: Wed Jan 20, 2010 7:38 pm 
Newbie

Joined: Fri Nov 30, 2007 1:39 am
Posts: 1
I see similar behavior as the OP - I get an NPE on isBag() when trying to left join fetch a @CollectionOfElements of type Map<String,String>. Bug imo.


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