-->
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.  [ 2 posts ] 
Author Message
 Post subject: Polymorphic Proxies for Lazy Loading
PostPosted: Sun Jun 13, 2004 2:49 pm 
Newbie

Joined: Sun Jun 13, 2004 12:53 pm
Posts: 2
I've been working with Hibernate for a week or so now migrating an existing persistence framework and I came across an issue. Does Hibernate have a built in mechanism for creating proxies which are of the correct type in a polymorphic association? For example, if I have the following classes:

Code:
public class Role {
     public Entity getEntity() {...}
     public void setEntity(Entity entity) {...}
}

public class Entity {}
public class Person extends Entity {}
public class Organization extends Entity {}


with the following mappings:

Code:
<class name="Role" table="Roles">
     <id .../>
     <many-to-one name="entity" column="entityId" class="Entity"/>
</class>

<class name="Entity" table="Entities" lazy="true">
     <id .../>
     <joined-subclass name="Person" table="Persons" lazy="true">
          <key .../>
     </joined-subclass>
     <joined-subclass name="Organization" table="Organizations" lazy="true">
          <key .../>
     </joined-subclass>
</class>


I would like for the proxy to the Entity to be of the correct type (i.e. either Person or Organization) when I load the Role from the database. I realize that something similar can be done using interface proxies. However, my understanding (and please correct me if I'm wrong) is that the resulting proxy would implement both Person AND Organization. I've tried this before and run into ClassCastExceptions when trying to execute certain methods on the resulting proxy. Not to mention that this would break "instance of".

Of course, I realize why this must be done this way, since there is really no simple way to determine the correct most derived type of the resulting proxy. However, I can think of 2 ways in which this could be done. Of course this is all moot if Hibernate can already do this stuff and I just haven't been able to figure out the magical incantation ;)

1) When the query to load the Role is generated, do outer joins with the Entities tables to determine the correct type to proxy. For example, the resulting query might look like:

Code:
select R.id, R.entityId, case when P.id is not null then 1 when O.id is not null then 2 when E.id is not null then 0 end as entityClass from Roles R left outer join Entities E on R.entityId=E.id left outer join Persons P on E.id=P.id left outer join Organizations O on E.id = O.id where R.id=?


Hopefully that's not too messed up, my SQL is not great ;) The obvious problem with that is that it does a lot more joins that would be necessary if we wern't trying to fetch the type of the proxied class. If the class hierarchy is large this might be prohibitive. However, it might be nice if there was an option to do it. I'm sure it would be possible to implement this in Hibernate using a custom persister but I haven't got a clue how. The 2nd option I WAS able to implement with a custom persister.

2) When the proxy is created, do a query to determine the type of the class to proxy. The obvious drawback to this is that you're now doing a query to create the proxy which doesn't seem very smart. Of course it should be a pretty efficient query and would look something like this:

Code:
select case when P.id is not null then 1 when O.id is not null then 2 when E.id is not null then 0 end as entityClass from Entities E left outer join Persons P on E.id=P.id left outer join Organizations O on E.id = O.id where E.id=?


One might be able to argue that if we are going to do this query, why not just go ahead and load the Entity? This is probably a perfectly valid argument. It would be nice to at least have the option though. If the Entity class has a lot of data, this may end up being faster in practice (especially if the initialization never gets invoked). Also it provides for the ability to halt the loading of the object graph at a correctly typed proxy, for the cases where an Entity is associated with other objects. Of course, if the object does end up getting initialized, we've now done 2 queries instead of one. But at least the Entity object is of the correct type ;)

This is actually how I handled this issue in a persistence framework I built before switching to Hibernate (which is wonderful by the way, great framework). It worked very well in practice and I never had any performance issues (although we don't have a ton of users and our database is on the same machine as the application). Of course, there may be some fundamental flaw in one or both of these methods but it seems like they would work to me.

Alright, so I mentioned I was able to get this working using a custom persister (really just a custom ProxyFactory). If anyone's interested I can post the code for it here.

To the Hibernate experts, if there's another way to do what I'm trying to do which is already built into Hibernate then please let me know. If not then maybe something like this would be a good thing to add in future versions.

Thanks in advance for your time,
Eric


Top
 Profile  
 
 Post subject: discriminator column
PostPosted: Mon Jun 14, 2004 2:17 pm 
Newbie

Joined: Sun Jun 13, 2004 12:53 pm
Posts: 2
Actually, it seems like both examples that I mentioned above could be simplified and would be more efficient if you could specify a discriminator column with a table-per-subclass mapping (joined-subclass). This could reduce the number of joins in the query. I think that's a good thing although it probably depends on the RDBMS.

According to the documentation though, discriminator columns are only allowed when using the table-per-class-hierarchy mapping strategy. Would it be a useful optimization at all to allow them on table-per-subclass mappings as well or would it just complexify things too much?


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