-->
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: Class inheritance: Two subclasses with same identifier
PostPosted: Tue Feb 21, 2006 10:03 am 
Beginner
Beginner

Joined: Wed Sep 07, 2005 9:57 am
Posts: 20
3.0.5


Code:
<hibernate-mapping package="com.carma.console.maintenance.company">
   <class name="RaasCompany" schema="respraas" table="COMPANY" lazy="true" mutable="false">
<!--       Meta attributes for code generation -->
      <meta attribute="scope-class">public abstract</meta>
      <meta attribute="scope-field">protected</meta>
      <meta attribute="implement-equals">true</meta>
      <meta attribute="extends">com.carma.console.BaseHibernateObject</meta>
      <meta attribute="generated-class">com.carma.console.maintenance.company.model.AbstractRaasCompany</meta>
<!--       Id -->
   

   <id name="companyKey" column="COMPANY_KEY" type="string">
         <meta attribute="use-in-tostring">true</meta>
         <generator class="assigned"></generator>
      </id>

      <property name="name" column="COMPANY_NAME" type="string" not-null="true" length="100">
         <meta attribute="use-in-tostring">true</meta>
         <meta attribute="use-in-equals">true</meta>
      </property>

      <many-to-one name="country" column="COUNTRY_KEY" class="com.carma.console.common.Country" not-null="true"></many-to-one>

      <many-to-one name="orgCountry" column="ORG_COUNTRY_KEY" class="com.carma.console.common.Country" not-null="false"></many-to-one>

      <property name="ModStamp" column="MOD_STAMP" type="date" not-null="false" length="7" />
      <property name="ModFlag" column="MOD_FLAG" type="string" not-null="false" length="1" />
      <property name="ModUser" column="MOD_USER" type="string" not-null="false" length="8" />

      <joined-subclass name="RaasRepertoireOwner" schema="respraas" table="REPERTOIRE_OWNER" lazy="true">
         <meta attribute="generated-class">com.carma.console.maintenance.company.model.AbstractRaasRepertoireOwner</meta>
         <key column="REP_OWNER_KEY"></key>
         <many-to-one name="raasProfitCenter" column="PROFIT_CENTER_KEY" class="com.carma.console.maintenance.company.RaasProfitCenter" />
         <property name="modStamp" column="MOD_STAMP" type="date" not-null="false" length="7" />
         <property name="modFlag" column="MOD_FLAG" type="string" not-null="false" length="1" />
         <property name="prodRepOwner" column="IS_PROD_REP_OWNER" type="true_false" not-null="false" length="1" />
      </joined-subclass>

      
      <joined-subclass name="RaasProfitCenter" schema="respraas" table="PROFIT_CENTER" lazy="true"  >
         <meta attribute="generated-class">com.carma.console.maintenance.company.model.AbstractRaasProfitCenter</meta>
         <key column="PROFIT_CENTER_KEY"></key>
         <property name="modStamp" column="MOD_STAMP" type="date" not-null="false" length="7" />
         <property name="modFlag" column="MOD_FLAG" type="string" not-null="false" length="1" />
         <property name="modUser" column="MOD_USER" type="string" not-null="false" length="8" />
      </joined-subclass>
   </class>
</hibernate-mapping>


Hi,

I have a class 'RaasCompany' which has two subclasses 'RaasRepertoireOwner' and 'RaasProfitCenter'. We are using a table per subclass strategy, eg. we have a company, repertoireowner and profitcenter table.

The company with the key 1 could be a repertoire owner and at the same time it could be a profit center. There is also a n-1 relationship between repertoire owner and profitcenter. It can be the case that for the repertoire owner (company id=1) the profit center is the same company (also id=1).

Now when I load this repertoire owner the profit center also gets loaded but instead of loading a RaasProfitCenter class the already loaded RaasRepertoireOwner is taken from the session. This is because they same have the same id and the same rootEntityName.

I can solve my problem by adapting the org.hibernate.engine.EntityKey-classes equals and hashcode methods so that instead of the rootEntityName they use the entityName. Then the entity is not found in the session and loaded properly.

Now I am wondering:
-Did I miss something and I can achieve this more easily
-Is it a bad idea to change the equals and the hashcode method of the EntityKey class

As far as I understand for Hibernate an entity with the same id can not be two different sub-classes of the same parent-class. But this is exaclty what I need. Is this an unresonably requirement?

Any comment is appreciated.

Thanks,
Ronald


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 21, 2006 11:10 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Yes, unfortunately for you it is an unreasonable requirement. You're expecting hibernate to provide multiple inheritance (RaasRepertoireOwner sometimes extends RaasCompany, and sometimes it extends RaasCompany), but there's nothing that it can do to do that. Java doesn't allow multiple inheritance.

This is a perfect example of when delegation is better than polymorphism. You'll need to change your class hierarchy and your mapping so that it isn't modeling the relationships in a "is-a" way, but rather in a "has-a" way. So RaasCompany gets two one-to-one relationships, one to RaasRepertoireOwner and one to RaasProfitCenter. Then you can have you implementation classes defer to the appropriate mapped class.

The only alternative would be to have four different, unrelated mappings: RaasCompany, RaasProfitCenter, RaasRepertoireOwner and RaasRepertoireOwnerProfitCenter.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 3:44 am 
Beginner
Beginner

Joined: Wed Sep 07, 2005 9:57 am
Posts: 20
Hi,

thanks for your answer.

Nevertheless you must have misunderstood me. I am not talking about multiple inheritance here. A RaasProfitCenter inherits from RaasCompany and RaasRepertoireOwner also inherits from RaasCompany. Every class only has one parent class.

RaasProfitCenter is adding information to a RaasCompany and RaasRepertoireOwner is also adding information to a RaasCompany. Now a RaasCompany can be a RepertoireOwner and a ProfitCenter (and therefore the RepertoireOwner and the ProfitCenter will have the same id).

I can model this beautifully in Java - no multiple inheritance here.

The only problem is that hibernate, once it loaded the RepertoireOwner into the session, it will not load the ProfitCenter (with the same id) as the EntityKey-classes bases its equals and hashcode methods on the name of the parent class.

Ronald


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 4:25 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
You'll have to explain the java inheritance model to me then.
ronaldploeger wrote:
Now a RaasCompany can be a RepertoireOwner and a ProfitCenter (and therefore the RepertoireOwner and the ProfitCenter will have the same id).

I believe that you're modelling this as two objects, a RaasRepertoireOwner and a RaasProfitCenter. These classes both extend RaasCompany. Therefore, one RaasCompany is modelled by two objects, unrelated except by id (which is obviously identical). This id is the only thing that hibernate has to relate a java object with a database row. One id relates to one RaasCompany, which might be a RaasRepertoireOwner or a RaasProfitCenter, but not both. You are faking mulitple inheritance by using the same id to represent two objects. I stand by my previous post. You do have unreasonable expectations, both of hibernate and polymorphism.

If you want to have hibernate use one id to represent two different objects, then you must tell it to look in two different tables for those objects. That is, the classes cannot be related (though they can be associated). At least one of RaasProfitCenter or RaasRepertoireOwner must follow the "has-a" relationship with RaasCompany, instead of the "is-a". Ask yourself: is "ProfitCenter" a type of company (is-a), or a role that a company plays (has-a). The same applies to "RepertoireOwner". Obviously I don't know what any of these things are, but it sounds to me like both are roles that a company plays, and thus should not inherit from RaasCompany.

There are many papers about this around. Have a read of the first pattern (delegation) in this paper, it's pretty good. http://www.laputan.org/pub/patterns/grand/fundamental.pdf


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 23, 2006 3:44 am 
Beginner
Beginner

Joined: Wed Sep 07, 2005 9:57 am
Posts: 20
Hi,

thanks for the time you spend on my problem. You definitly got me started thinking from different perspectives. I am still not 100% sure that I agree but I can see your point and will read thru the reference you mentioned. Thanks for this.

Ronald


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 24, 2006 3:28 am 
Beginner
Beginner

Joined: Wed Sep 07, 2005 9:57 am
Posts: 20
Hi,

you were right. I agree completely with you - thanks for the insight.

Ronald


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.