-->
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: Mapping legacy polymorphic hierarchy
PostPosted: Tue Feb 10, 2004 1:54 pm 
Newbie

Joined: Mon Feb 09, 2004 2:14 pm
Posts: 14
I understand (I think) the three strategies for mapping that Hibernate supports. However, I have a mapping strategy from a legacy persistence mechanism that I have to match. Changing the database isn't an option - we have terabytes of data stored and millions of lines of legacy code that needs to be preserved.

The mapping strategy uses a table-per-subclass, with discriminator, all classes concrete. So, for example I could have

class Party
{
}


class Person extends Party
{
}


class Customer extends Person
{
}

Each of Party, Person and Customer have attributes and are mapped to distinct tables. Party has a discriminator column (it happens to be an int) and Person and Customer have primary key constrains to their superclass table primary key. (IOW, Person primary key and Party primary key are the same value).

Party, Person, and Customer are all concrete objects. The current system allows for querying of Party (possibly returning Person and Customer objects) as well as Person (possibly returning Customer objects) and Customer directly. The queries in all cases return the class discriminator which is used to populate the more derived layers lazily. (So if a Person query is executed and a Customer is returned, the Customer attributes are only accessed when/if used).

Note that the hierarchy can be several layers deep - I've illustrated with three layers, but in reality the model extends to at least seven layers. I'm not interested in a discussion about whether this is a good or bad model - that is unfortunately irrelevant. What I'm trying to do is find out how to support this model with Hibernate, or if I have to look for another tool.

Any help would be appreciated. RTFM greatfully accepted with a reference to the right page(s).


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 2:51 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
This strategy is not supported (and is Bad, anyway).


Top
 Profile  
 
 Post subject: Alas
PostPosted: Tue Feb 10, 2004 5:26 pm 
Newbie

Joined: Mon Feb 09, 2004 2:14 pm
Posts: 14
Well, I'm not sure I agree with the fact that it's "Bad". We've been using it in production for nearly a decade with pretty good results. (Several million transactions per day.) But that's a personal opinion, I suppose.

I'm more interested in whether the Hibernate team would be interested in working with us to support our legacy data, or if the expectation is that all Hibernate projects have to start from scratch. My impression is the latter, which is unfortunate.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2004 5:30 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
You can always submit a patch to JIRA and let people vote. We are also implementing features on request if you need professional development or production support.

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 11, 2004 11:54 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
...do your framework "magically" fetch the remaining attributes of a Customer first when you do x.getSomeCustomerAttribute(); ?

Or do you do something like session.fillIn(Customer.class, x);

or something ?

You do know that you could do part of this via the LightWeight pattern - if I understand you correctly.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject: yes, it's magic
PostPosted: Wed Feb 11, 2004 12:17 pm 
Newbie

Joined: Mon Feb 09, 2004 2:14 pm
Posts: 14
Yes, the framework automatically retrieves the unretrieved attributes - actually it will retrieve all attributes at the table level. But it creates the right class when the object is retrieved - so if I retrieve a list of Persons, some of whom happen to be Customers, those objects are retrieve as partially hollow Customer instances.

I'm not sure Lightweight fits the bill, as it wouldn't allow for the polymorphic retrieves. So (if I understand Lightweight right) I would retrieve a Person, but to get to the Customer (heavy class) I would have to re-retrieve (which I'm not sure I could even do as it would retrieve the same database row as the original Person object).

I've considered facades for this, but the maintanence of the facade objects is a pain, and what we were hoping to get in the engine in the first place.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 11, 2004 3:27 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
...but that's very nasty - it requires proxy'ing the class and if the session closes the get/setters would/should throw an exception to "warn" you...

Is it a big problem to fetch the whole customer ?

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject: Why full customer
PostPosted: Wed Feb 11, 2004 3:44 pm 
Newbie

Joined: Mon Feb 09, 2004 2:14 pm
Posts: 14
It isn't that bad to retrieve a customer - it's just a question of waste if the customer is never needed.

More background might help. This application data model is shared across multiple (dozens) of applications. An application retrieving Person objects may or may not need to manipulate Customer information. In any event, it is certainly the case that you will get heterogeneous lists of Person instances, and even in a single application it is not clear that Customer level information is required.

Take the following imaginary use case. We retrieve a list of claimants for an insurance claim. A subset of these are Customers. The list is retrieved as Person objects. If we need Customer information (either through specializing the retrieve claimant OR through accessing the same record via a different flow path - e.g. accessing the Customer via their Policy information) we go back to the database to get the Customer information.

Persons can also be an number of other subtypes. We can't predict which are necessary at query time. So we could attempt to join to all the subclasses - but that is likely to bring back a LOT of unnecessary data, and require a LOT of unnecessary joins to the database. In the pathological case, attempting to retrieve an object high up in the hierarchy would attempt a join across a substantial portion of the database. (Our database runs at about 485 tables last time I counted)

That's the value of the discriminant - it lets us tell the real class of the object so we can go back and get the right information if and when we need it. Yes, if the database connection craps out before that happens we're in trouble - but the likelihood of that happening is very, very small (like measured in years small). And we're in trouble at that point anyhow.

We didn't proxy the class in the existing implementation. We proxied the attributes, effectively, so that they know to retrieve themselves (their table) on first access.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 11, 2004 5:15 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Personally, I find the n+1 selects that naturally result in this strategy to be FAR more problematic than some "unnecessary" joins.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 11, 2004 8:43 pm 
Newbie

Joined: Mon Feb 09, 2004 2:14 pm
Posts: 14
I can appreciate that. It is certainly a tradeoff. It works well for us, and given the size and volume of our transactions I'm not sure any other strategy would. The key tradeoff is the number of times you have to downcast the objects in order to get the work done. If this is not a sizeable percentage of time, then the extra round-trips are mitigated.

We did a pretty deep analysis when we designed the system, and while there are certainly aspects we would change (lowering the max height of the inheritence structure) I question whether we would adopt an inherently different strategy. Our feeling was that when your tables have tens or hundreds of millions of rows in them, casting a suspect eye on joins - even primary key constrained ones - is a Good Thing. Perhaps you disagree.

Also consider the fact that some of the subclass tables are sparsely populated with respect to the superclass. For example, we have far, far more People entries than Employees - even though Employee is a subclass of People. Joining on this table in the general case would have a low hit probability but seems to be required by the strategy you advocate for.

Should Employee be a role rather than a subclass? Likely so. Given the opportunity I would have modeled it differently a decade ago. However, that horse has left the barn and the cost to remodel hasn't been justified from a business perspective.

However, the lazy evaluation of the hollow portions of the data still begs the original question. I was trying to determine if Hibernate would support this mapping strategy AT ALL, which it appears to not to.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 11, 2004 9:19 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
However, the lazy evaluation of the hollow portions of the data still begs the original question. I was trying to determine if Hibernate would support this mapping strategy AT ALL, which it appears to not to.


I think it does, in fact. The disciminator column is actually not needed, as long as you are happy to always load using joins (but, of course, having the discriminator does not /hurt/).


Top
 Profile  
 
 Post subject: This is news...
PostPosted: Wed Feb 11, 2004 9:51 pm 
Newbie

Joined: Mon Feb 09, 2004 2:14 pm
Posts: 14
This is great news - and contrary to what I've seen so far.

Any pointers to examples that demonstrate this kind of mapping would be deeply appreciated. I've been searching with no luck, and my reading of the relevant section of the documentation hasn't led to success yet.

Many thanks


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 12, 2004 1:20 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
Just make an ordinary <joined-subclass> .... it should be straight forward....you just only need to specify the discriminator column in the top most subclass.

_________________
Max
Don't forget to rate


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.