-->
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.  [ 17 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Selective (or lazy) association loading at runtime?
PostPosted: Thu Apr 15, 2004 11:08 am 
Regular
Regular

Joined: Tue Dec 02, 2003 6:25 pm
Posts: 61
Location: Dallas, TX
Is there anyway to tell Hibernate (at runtime) to NOT to load an association at all?

I have several screens in my web app where I need to show a child collection, for example a portfolio of 100 real estate properties, from which the user will select one to view/edit. Loading that collection involves a lot of SQL due to a lot of xxx-to-one relationships (I can't use proxies for them because they might be null). and it is unnecessary because the view only needs four attributes and two of the associations.

I was able to write an HQL query to get what I need, and it was blazingly fast. I'll probably end up writing some sort of jsp tag for running HQL queries and alter my page accordingly.

But I wanted to ask if there was any way to disable most of the associations programmatically at runtime for my summary view while letting the associations load normally for my detailed view, because I would rather work with partially instantiated domain objects than with a List of Object arrays returned by an HQL query.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 12:02 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
lazy = true

and if you want a lazy collection to be loaded query like this "from A as a left FETCH join a.collection"

Anthony


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 12:25 pm 
Regular
Regular

Joined: Tue Dec 02, 2003 6:25 pm
Posts: 61
Location: Dallas, TX
I may not have been clear before. I understand how to deal with lazy collections.

What I am trying to do is specify which elements of the object graph I want to retrieve. I have a huge object graph, and I have a view which knows exactly what it needs, which is not very much at all.

I would like to select only the elements of the graph that I need to display. I don't actually care about lazy loading (proxies) at all -- I don't need lazy loading because my view would never load anything beyond what it had requested.

I think I know what I'm going to do, but I wanted to bounce it off you folks. Because it seems like it would be a common problem for web apps that need to present the user with a large collection of objects from which to select.

Let's say I have a Loan object that has a lazily loaded set of Property objects. The problem is, loading that collection takes a LOT of SQL (due to a lot of many-to-one and one-to-one relationships), and I find that I usually don't need more than a handful of attributes. So using Hibernate's standard lazy loading is sort of overkill in terms of SQL and memory.

Alternatively, I could run an HQL query where I specify exactly what I need. for example:

Code:
select
p.id,
p.propertyType,
p.name,
p.address
from Property p where p.portfolio = ?


The query runs very quickly and it returns everything I need. I'll probably end up doing this and writing a tag like

Code:
<my:find query="select..." id="properties"/>


I guess I was wondering
A. Whether this seems reasonable
B. Whether anyone else has done anything like this
C. Whether there is a way to do this programmatically, using Criteria

With Criteria, there is a way to setFetchMode("someAssociation", FetchMode.LAZY), but all that does is disable outer-join. I guess I'm wondering if there is a way to do something like FetchMode.DO_NOT_FETCH. There probably isn't. Just wanted to ask.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 12:49 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
Use a query.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 2:08 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
1- if you declare all to-many associations with lazy = true and all to-one associations with a proxy, then the x queries won't be generated right?
2- if you use "advanced queries" to fetch only associations you need, you will retrieve what you want

there is a limitation
A 1----* B 1-----* C

with all lazy=true and proxies
1- select a from A as a will return only all A instances
2- select a from A as a left FETCH join a.bs, will return all a instances with B collections loaded but not C
3- now if you also want to load Collections, you can't do it with only one generated SQL, you'll be in the n+1 problem since
select a from A as a left FETCH join a.bs as bs left FETCH join bs.cs isn't correct


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 2:22 pm 
Regular
Regular

Joined: Tue Dec 02, 2003 6:25 pm
Posts: 61
Location: Dallas, TX
Quote:
2- if you use "advanced queries" to fetch only associations you need, you will retrieve what you want


I think you're trying to solve a different problem than what I am talking about. As I said, I don't have any problems with lazy collections. I am not trying to do eager (outer-join) fetching of a lazy collection. I know how to do eager fetching if I want to. I was wondering if it was possible to disable (not make lazy) associations in a Criteria query at runtime.


Quote:
1- if you declare all to-many associations with lazy = true and all to-one associations with a proxy, then the x queries won't be generated right?


one-to-one associations can only be proxied if the -to-one side will never be null. I've got a bunch of one-to-zero-or-one associations that cannot be proxied. So even with lazy collections, loading a single Property involves a LOT of joins and returns data that I don't need.

Essentially the question was whether or not I could completely disable/ignore an association at runtime, using something like the Criteria API.

I think I will just stick with the solution I outlined above, using HQL to get a List of Object arrays, rather than partially instantiated business objects.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 2:40 pm 
Regular
Regular

Joined: Fri Jan 16, 2004 4:48 am
Posts: 56
Form what I understand , you have say

A - B

When you query A, you want to get only A's eben if you have a slect criteria for some property on B

you can specify

select distinct a from A as a left outer join a.b where b.something = 'x'

This will return only A's where you have related B matching criteria b.something = 'x' without actually loading B


Is this what you are looking for ?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 3:01 pm 
Regular
Regular

Joined: Tue Dec 02, 2003 6:25 pm
Posts: 61
Location: Dallas, TX
ok...

A has one-to-many B (lazy="true")
B has 1-to-zero-or-1 C
C has 1-to-zero-or-1 D

C and D can NOT be proxied because they might be null.

So, every time I try to load a B, Hibernate will ALWAYS load C and D.

There is NO way (that I know of) to make C or D lazy. This is the problem.

I have a screen that needs to display B.property1 and A.property2. I do not want to load C or D. But there is no way to load B without loading C or D.

The only thing I can do is write an HQL query where I specify each attribute that I need. So if I needed 20 attributes of B, I would have to specify them explicitly, i.e.

Code:
select b.a.1,b.1, b.2,.....b.20 from B b


If I run this query, it will not join to C or D, and that is what I want. But it doesn't return a domain object, just Object arrays, and it's kind of a pain to have to specify each attribute. I would rather say "load B, except for the association to C".

So, again, this problem is only loosely related to collections (-to-many). If I use a lazy collection, it will always load C and D, as well as all the Bs that belong to A. Consequently, I will probably NEVER use the actual collection, because it ALWAYS returns more than I need. Instead, I will end up using an HQL query whenever I want to list the items in a collection.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 3:04 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
wfassett,
don't get nervous, it seems many users just don't understand your need.
but i'll try again ;)

Is that right: you only want to control which parts of an objects graph will be loaded in one query, is it?

you can compose a query to return an array of objects without problem but about the
Quote:
one-to-one associations can only be proxied if the -to-one side will never be null

what about changing your one-to-one association to a many-to-one association, i think i've seen it somewhere in another post


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 3:17 pm 
Regular
Regular

Joined: Tue Dec 02, 2003 6:25 pm
Posts: 61
Location: Dallas, TX
Yes you understand, delpouve.

I was just surprised that there is not something like a FetchMode.NONE, because it seems that it might be useful in some cases.

Quote:
what about changing your one-to-one association to a many-to-one association, i think i've seen it somewhere in another post


Yes that's a good point, and that would work - I would just need to add a C_ID column to my B table, and then I could change the relationship to many-to-one and use a proxy to make it lazy.

I will probably play with both options, the query and the many-to-one. If speed was of the utmost importance, I would imagine the query would be the fastest in most cases. But I think I would prefer to stick with a more object-friendly solution by just changing the one-to-one relationships to one-to-many and using proxies.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 3:27 pm 
Pro
Pro

Joined: Tue Aug 26, 2003 1:24 pm
Posts: 213
Location: Richardson, TX
Hey, a fellow dallasite. :)

Possibly a variant of the lightweight class pattern is what you're after: http://www.hibernate.org/41.html Basically, define a different mapping for commonly used subsets of properties. A bit clunky, though.

You can change the mapping of a class at runtime, methinks. Check out net.sf.hibernate.mapping.PersistentClass and net.sf.hibernate.cfg.Configuration.getClassMapping(). I'm not sure it's a good idea, though.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 3:42 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
hibernate.max_fetch_depth
Set a maximum "depth" for the outer join fetch tree.
eg. recommended values between 0 and 3

http://www.hibernate.org/hib_docs/refer ... ation.html


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 3:59 pm 
Regular
Regular

Joined: Fri Jan 16, 2004 4:48 am
Posts: 56
I think FetchMode.NONE kind of flag to say not to load any association at loadtime (ovveriding config mapping and global settings ) seems to make more sense.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 15, 2004 5:32 pm 
Regular
Regular

Joined: Tue Dec 02, 2003 6:25 pm
Posts: 61
Location: Dallas, TX
Greg -

Great to know there's another Dallasite using Hibernate. Maybe we can compare notes sometime.

Yes the lightweight class pattern would also work. However, it seems like it's a bit more work (and I'm pretty lazy), and when I think about it I start having visions of a myriad of classes and mappings corresponding to each view. Well, that's overreacting, but it just seems like more work to maintain.

So I think I prefer to use either HQL queries or regular lazy-loading coupled with the many-to-one modification that delpouve recommended.

It does seem that something like FetchMode.NONE would be a useful feature for Criteria queries.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 25, 2006 2:46 am 
Newbie

Joined: Mon Sep 25, 2006 2:18 am
Posts: 3
I know that this is a rather old post but i have the same problem as above and i would like to know if this is solved.

What i want is either a way to dynamically (through the session perhaps) set the maximum fetch depth or FetchMode.NONE as was suggested here.

Is this something that can be done in Hibernate3 ?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 17 posts ]  Go to page 1, 2  Next

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.