-->
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.  [ 13 posts ] 
Author Message
 Post subject: Fetching with left joins
PostPosted: Sat Sep 03, 2005 6:15 pm 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
Hey,

I have an object model where I have three classes with 1-* relations between them. They look like this:

A -1-*> B -1-*> C

As you can see, A has a bunch of B's as children and B has a bunch of C's as children.

The following hql query is more then logical to grab the whole tree in one query:

Code:
from A A left join fetch A.Children B left join fetch B.Children


of course this will result in two LEFT JOINs in the SQL query which is perfectly fine.
Why can't NHibernate handle this? A.Children will not hold all the related B's, although it should.

What is the fastest way to load this graph of objects? I keep ending up running N+1 queries which sucks and I'm not sure how else I could pull this off.

Any idea?

Thanks,
RGabo


Last edited by RGabo on Wed Sep 07, 2005 10:48 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 03, 2005 6:57 pm 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
Now that I've read a little more about the issue, one question came up in my mind:

Why is hibernate.max_fetch_depth not implemented? ;)

..and what's the workaround..

RGab


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 10:50 pm 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
Guys,

I can't believe nobody has an answer to this trivial question. All I want is to load objects where the root object has a one-to-many relationship, where the objects on the many end have another one-to-many relationship.

In Hibernate, this can be controlled with the maximum deepness of a fetch. It seemed to me, NHibernate can't really cope with this.

The problem I am facing is trivial. A country has many states, where the states have many cities. How can I grab those objects in one query?

Thanks,
RGabo


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 08, 2005 8:52 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
max_fetch_depth works in the latest CVS version. As for your problem, unfortunately Hibernate 2.1 HQL translator is coded in such a way as to allow only one collection to be fetched in a query, so this won't be fixed until after 1.0 is released. For now I only added a check for this problem to the code.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 08, 2005 10:10 am 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
sergey wrote:
max_fetch_depth works in the latest CVS version. As for your problem, unfortunately Hibernate 2.1 HQL translator is coded in such a way as to allow only one collection to be fetched in a query, so this won't be fixed until after 1.0 is released. For now I only added a check for this problem to the code.


But would it work if I use ICriteria? If not, what kind of workaround or tip can you give me to avoid N+1 problems and successfully load that graph fast!

It would be really helpful and important for me!

Thanks!
RGabo


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 09, 2005 3:19 am 
Senior
Senior

Joined: Thu Aug 25, 2005 3:35 am
Posts: 160
rgabo,

i have exactly the same problem. Did you find a good workaround:?:


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 09, 2005 4:28 am 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
TheShark wrote:
rgabo,

i have exactly the same problem. Did you find a good workaround:?:


Well, I'm checking right now if the implementation of fetching multiple levels deep in the latest CVS source tree works or not. It is different from the latest released 0.9.1.0 source so I'm optimistic.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 09, 2005 5:33 am 
Senior
Senior

Joined: Thu Aug 25, 2005 3:35 am
Posts: 160
RGabo wrote:
Well, I'm checking right now if the implementation of fetching multiple levels deep in the latest CVS source tree works or not. It is different from the latest released 0.9.1.0 source so I'm optimistic.


Great, I am extremely interested in the results. I'm just starting to use nhibernate and finding lots of cool stuff, but also missing functionality.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 09, 2005 6:55 am 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
TheShark wrote:
RGabo wrote:
Well, I'm checking right now if the implementation of fetching multiple levels deep in the latest CVS source tree works or not. It is different from the latest released 0.9.1.0 source so I'm optimistic.


Great, I am extremely interested in the results. I'm just starting to use nhibernate and finding lots of cool stuff, but also missing functionality.


Well, It seems to me the reason it won't go deeper is because it allows only one collection association or better put: fetch in a query. This would be really bad news. Sergey, can you confirm this?

RGab


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 09, 2005 7:36 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I believe that fetching multiple collections in one query was enabled in Hibernate 3 only recently. Fetching multiple many-to-one's should work ok. The Loader accepts only one collection to load in its methods, making it work with multiple collections would be quite an effort and I don't want to do it until after 1.0 is released. As to why it was coded that way, I don't know, probably it was much easier to code for Hibernate Team.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 09, 2005 11:53 pm 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
sergey wrote:
I believe that fetching multiple collections in one query was enabled in Hibernate 3 only recently. Fetching multiple many-to-one's should work ok. The Loader accepts only one collection to load in its methods, making it work with multiple collections would be quite an effort and I don't want to do it until after 1.0 is released. As to why it was coded that way, I don't know, probably it was much easier to code for Hibernate Team.


Sergey, you rock, thanks for the quick confirmation. It is bad news indeed but I need some sort of recommendation from you. What I do now takes N+1 queries for N objects with one-to-many relationships two levels deep and a fairly high number of cache hits of course when I actually query the root objects itself. It takes longer than I would want to already and the problem is that N could increase substantially.

What would be your final recommendation? I almost have no time to do my best, what could be the best? Schema change to have only one one-to-many? Some sort of special query? Advanced caching of stuff? Incremental loading? Some sort of lazy loading?

What I know is that I need the full graph for one of the features of the app. I can lazy load the ones that show up in the UI (30 or so). It will introduce a little latency but that's fine, it's not production grade anyway.

Just show me the path, you don't even have to lead me. My fate is in your hands, Sergey ;)

Thanks,
Gabor


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 10, 2005 9:09 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
What about this:
Code:
from Children1 c left join fetch c.A left join fetch c.Children2

:)

("left join fetch c.A" is required only if A is lazy loaded)

The downside is that A.Children1 will not be initialized! And its initialization will need accessing the database (even if all its items are all in the cache) :(
Anyway, it might be the solution if you can work it around...

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 12, 2005 12:39 am 
Newbie

Joined: Mon Jun 27, 2005 12:06 am
Posts: 18
Location: San Francisco, CA
KPixel wrote:
What about this:
Code:
from Children1 c left join fetch c.A left join fetch c.Children2

:)

("left join fetch c.A" is required only if A is lazy loaded)

The downside is that A.Children1 will not be initialized! And its initialization will need accessing the database (even if all its items are all in the cache) :(
Anyway, it might be the solution if you can work it around...


Well, at least we reduced it from N+1 queries to 2 queries! That's already an improvement.. Makes a lot of sense what you did! This is how I did:

Code:
session.CreateCriteria(typeof(State)).SetFetchMode("Cities", FetchMode.Eager)
                                     .SetFetchMode("Country", FetchMode.Eager)
                                     .List();

IList countries = session.CreateCriteria(typeof(Country)).SetFetchMode("States", FetchMode.Eager)
                                                  .ListDistinct();


I am wrapping around NHibernate so the syntax is slightly different but you get the point. Hope that helps! Any other suggestions?


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