-->
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.  [ 6 posts ] 
Author Message
 Post subject: "Unmanaged" Associations -- purely declarative ass
PostPosted: Tue Mar 23, 2004 9:13 pm 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
I would like to use Hibernate associations in a way that appears to differ from the intended usage pattern. After reading the Hibernate docs and forums, and a good deal of experimenting, I have concluded that Hibernate aims to "fully manage" associations. In particular, if you load an object, Hibernate will either immediately or lazily load associated entities.

I'd like to instead declare associations that give me full control over loading, saving/updating, and deleting the associated entities. I don't want Hibernate to be "smart" and try to help me out for these associations -- although in other parts of our application, we love its intelligence. I want "Hibernate Light" :)

For context, I'm implementing a relatively flexible data/object model for hierarchies, roughly following the organizational pattern described by Martin Fowler: http://www.martinfowler.com/apsupp/accountability.pdf.

At the heart of my model are Nodes and Relationships. Each relationship has a foreign key to a Parent and a Child node, as well as metadata such as the relationship type. Individual nodes might be related to thousands of other nodes.

I considered using Hibernate Collections to model the association of nodes to other nodes via relationships, but they don't appear to be flexible enough for my needs: we need to query for children based on relationship type, on attributes of the related nodes, to query for entire "subtrees" at once, to load only the "first 100 children", etc. Collections did not seem flexible/powerful enough to do this work efficiently in the database, although they'd be a great aid for managing small objects graphs in the JVM. We were ruminating that it would be nice if there were a facility "parameterize" Collections at runtime with "filters" (subqueries).

I also considered using Proxies, but lazy loading really doesn't address the problem. In fact, it usually makes things worse as our goal is to minimize the number of queries required to load specific subsets of a hierarchy graph.

The problem with straightforward many-to-one associations is that Hibernate insists on doing outer joins on all associations. (Things are even worse if outer joins are disabled, as Hibernate just falls back on separatequeries.) So if, for instance, I want to query for all "child" relationships and "child nodes" of a specific parent node, and the Relationship mapping declares many-to-one mappings to its parent and child Nodes, the query Hibernate executes includes two outer joins: one to fetch the relationship's children and another to fetch its parent. This happens even though I already have the (single) parent node. In addition to being an overly complex query, the result set is much larger than it needs to be because it includes numerous unwanted copies of the parent node. Finally, once the hierarchy object graph has been reconstituted in the JVM, I don't want the relationship objects to have references to distinct copies of the same parent node; I want them to all refer to a single parent node object.

So why do I want to declare these associations? So that I can utilize them in Hibernate queries that we hand code to exploit the very nifty "fetch join" feature. But the "side effects" of declaring the associations are pushing my team towards not using them -- we'll just have to construct the object graph ourselves from Lists of nodes and relationships returned by Hibernate.

I hope this rather lengthy inquiry makes sense -- I'm not clear if I just don't understand things or if I'm making a feature request. Any help is much appreciated!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 23, 2004 9:15 pm 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
p.s. my apologies for the subject line -- it appears that the Forum truncated my length subject line rather profanely :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 23, 2004 9:39 pm 
Pro
Pro

Joined: Tue Aug 26, 2003 1:24 pm
Posts: 213
Location: Richardson, TX
Quote:
At the heart of my model are Nodes and Relationships. Each relationship has a foreign key to a Parent and a Child node, as well as metadata such as the relationship type.

This thread has an example of creating a many-to-one relationship with relation attributes:
http://forum.hibernate.org/viewtopic.php?t=926662&highlight=manytomany+extra

If I were to do this I'd probably use a bag instead of a set (for efficiency) and cache the collection.

Quote:
I considered using Hibernate Collections to model the association of nodes to other nodes via relationships, but they don't appear to be flexible enough for my needs

They might be more flexible than you think... :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 23, 2004 9:46 pm 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
greg_barton wrote:
This thread has an example of creating a many-to-one relationship with relation attributes:
http://forum.hibernate.org/viewtopic.php?t=926662&highlight=manytomany+extra


Thanks for this pointer, but the thread doesn't address my fundamental problem. The issue is not whether Hibernate is capable of modeling a many-to-many relationship, it is how it manages the objects, when it loads/saves/updates objects, and so on.

A colleague of mine reduced it nicely: "It would be great to be able to declare an association as 'lazy', but then use that association in a query in a way that 'forces immediate load' to override the lazy default." My version of this is that I want to explicitly manage the association, taking advantage of Hibernate's automation when and where it helps (and disabling it where it gets in my way or causes performance problems).

I suspect this is a rather large feature request, and I doubt I fully understand the implications in terms of how Hibernate manages object associations within the Session.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 23, 2004 9:57 pm 
Pro
Pro

Joined: Tue Aug 26, 2003 1:24 pm
Posts: 213
Location: Richardson, TX
I think that if your goal is to minimize queries just liberally use cache. Memory is cheap. :)

Quote:
declare an association as 'lazy', but then use that association in a query in a way that 'forces immediate load' to override the lazy default

How is this different from a proxy?

Possibly what you need is a "lightweight class" mapping for some aspects of your data model, loading up other attributes by id when you need them?

http://www.hibernate.org/41.html


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 24, 2004 2:08 am 
Regular
Regular

Joined: Fri Dec 12, 2003 2:09 pm
Posts: 84
Location: San Francisco, USA
greg_barton wrote:
I think that if your goal is to minimize queries just liberally use cache. Memory is cheap. :)

hypernate wrote:
declare an association as 'lazy', but then use that association in a query in a way that 'forces immediate load' to override the lazy default


How is this different from a proxy?


Proxies load objects one-by-one. I want to run queries with complex JOINs and WHERE clauses and have Hibernate help me reconstitute the results into an object graph. I don't want to build a query engine in Java -- that's what the database does well, and that's how I want to use it :)

Memory is indeed cheap and we're happy to load in large subsets of the hierarchy graph into a Session -- but not the entire thing, and not even all children. We need to be able to scale to hierarchies with millions of records. The two options I see available to me in Hibernate -- eagerly fetch everything or lazily fetch records one-by-one using proxies -- are just not good enough. Your post has got me thinking that I do need to play more with proxies, however... maybe by declaring nodes as proxies I can get Hibernate to only load them in response to queries (I couldn't get Hibernate to do this when I tried last).

The principal issue with Collections is that Hibernate requires the "complete" set to be included, while as I said we want different subsets based on node and relationship properties. See Gavin's note at the bottom of this thread:

http://forum.hibernate.org/viewtopic.php?t=926652

I want to do precisely what he suggested is "strange": run various queries with FETCHes to eagerly join children with a WHERE clause specifying which children I want. There's no one to "combine" custom queries with Collections.

Thanks for the link on lightweight classes -- this may be useful to us elsewhere.


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