-->
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.  [ 10 posts ] 
Author Message
 Post subject: joined-subclass and getting super/sub-class
PostPosted: Wed May 04, 2005 11:38 am 
Beginner
Beginner

Joined: Wed Feb 09, 2005 3:27 pm
Posts: 29
I have a class hierarchy that looks like this:

Code:
           Person
   ----------|---------
   |                  |
Employee          Customer
   |
Manager


The database has one table for each class and each table contains the following data:

Code:
PERSON    PERSON_ID    NAME
          1            Bob
          2            Sally
          3            Mike
          4            Peter
          5            Andy
       
EMPLOYEE  EMPLOYEE_ID  HIRE_DATE
          2            02/02/02
          3            03/03/03
          4            04/04/04
         
MANAGER   MANAGER_ID   TITLE
          4            Department Manager
         
CUSTOMER  CUSTOMER_ID  CUSTOMER_SINCE
          2            01/01/01
          5            01/01/02


From this we can read that: Bob is just a person, Sally is a employee and a customer, Mike is a employee, Peter is a an employee and a manager, and Andy is a just a customer.

I'm using the following structure to map the inheritance:

Code:
<class name="Person" ...
  <joined-subclass name="Customer" ...
  <joined-subclass name="Employee" ...
    <joined-subclass name="Manager" ...


Now to the problem. If I call SessionImpl.get() passing it Employee.class and the identifier 1 then I will get an instance of Employee back. However, if I pass it the same class and 2 I get an instance of Customer back. Likewise, passing Person.class and 3 I'll get an Employee instance back.

What puzzles me is that I'm specifically asking for an Emplyee instance, yet Hibernate seems to do a little extra and bring me the sub-class. Why is this and is there a way to disable this behavior? The class for each type has some behind-the-scenes logic (an alternative data representation) that is different depending on what kind of object is being instantiated and I must be able to get exactly what I ask for (i.e. casting to the class I asked for is not an option due to the data structure backing the instance).

Any help is greatly appreciated!

Thanks,

-Kaare


Top
 Profile  
 
 Post subject: Re: joined-subclass and getting super/sub-class
PostPosted: Thu May 05, 2005 10:59 am 
Beginner
Beginner

Joined: Wed Feb 09, 2005 3:27 pm
Posts: 29
Can anyone from the Hibernate team confirm if this behavior is as designed or if this is a bug? If you need more details, please let me know what you need me to post.

Thanks,

-Kaare


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 05, 2005 2:23 pm 
Senior
Senior

Joined: Tue Feb 08, 2005 5:26 pm
Posts: 157
Location: Montréal, Québec - Canada
This is expected behavior.

Hibernate will issue polymorphic queries and return the specialized class that corresponds to your criteria.

Also, if you would define an attribute -employeeNumber- on Employee and issue the following query:
Code:
session.createCriteria(Person.class).add(Expression.eq("employeeNumber", whatevervalue)).list();

-> You would receive an Employee back because if an Employee inherits from a Person, then Employee IS a Person too.

I suggest you read this: http://www.hibernate.org/hib_docs/v3/re ... lymorphism

I hope this answers your questions,

Vincent

_________________
Vincent Giguère
J2EE Developer


Top
 Profile  
 
 Post subject: Re: joined-subclass and getting super/sub-class
PostPosted: Thu May 05, 2005 3:47 pm 
Beginner
Beginner

Joined: Wed Feb 09, 2005 3:27 pm
Posts: 29
Thanks, Vincent.

If this is as designed, there really ought to be a way to instruct Hibernate to instantiate an instance of the base-class (i.e. the class being asked for) as opposed to the sub-class (i.e. the specialized class). I'd find it strange if this is not the case since creating the specialized instance is likely to have a greater cost. If I really want the specialized class I'll just ask for it -- why take away the developer's ability to decide what the right thing to do is?

-Kaare


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 05, 2005 5:16 pm 
Senior
Senior

Joined: Tue Feb 08, 2005 5:26 pm
Posts: 157
Location: Montréal, Québec - Canada
In my opinion, I think you would run into problems if you were able to load a parent class instead of the actual sub-class implementation.

If your subclass only adds other attribute over the base class, then it might be fine, but if your subclass overrides the value of field defined on both tables, then i would make no sense to create the parent class.

I do not know of any workaround :(

Good luck :)

_________________
Vincent Giguère
J2EE Developer


Top
 Profile  
 
 Post subject: Re: joined-subclass and getting super/sub-class
PostPosted: Mon May 09, 2005 4:35 pm 
Beginner
Beginner

Joined: Wed Feb 09, 2005 3:27 pm
Posts: 29
vgiguere wrote:
In my opinion, I think you would run into problems if you were able to load a parent class instead of the actual sub-class implementation.

What kind of problems? I think it's perfectly valid to be able to get the super-class in order to avoid potentially costly operations associated with the sub-class. Anyway, I did some digging in the documentation and saw that there's a polymorphism=(implicit or explicit) attribute (on the class element) that looked promising. Unfortunately there's no visible difference in behavior... So are we talking about a bug? It seems like the design is addressing this so hopefully it's just an implementation bug.

Another thing that's weird is that whenever I have persons who are also employees and customers, I will usually get Employee instances, but occasionally there's a Customer instance being returned.

-Kaare


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 10, 2005 11:09 am 
Senior
Senior

Joined: Tue Feb 08, 2005 5:26 pm
Posts: 157
Location: Montréal, Québec - Canada
Hi,

Quote:
What kind of problems? I think it's perfectly valid to be able to get the super-class in order to avoid potentially costly operations associated with the sub-class


I was not talking about performance problems but more about data consistency problems, in the case that a parent attribute is overriden at the subclass level.

Let's say Person has a special field "specialField" with a value set to AA. Let's say that Customer overrides this value to BB. If you were to load a Person which is in fact a Customer, the value would be set to AA, and not to BB, which could be a problem.

I do not know if Hibernate can create an instance of Person and populate overriden fields with values from the Customer table. Maybe it can.

I agree with you that you should be able to perform the scenario described above. Typecasting a Customer into Person would adress the data override problem, but if your Customer overrides Person's behaviour, then you would have other problems.

Maybe inheritance is not a solution for your case.

Let me know if you find a way to load a java parent class with data coming from the subclass. I would like to know.

If I come upon something, I'll reply.

Good luck.

_________________
Vincent Giguère
J2EE Developer


Top
 Profile  
 
 Post subject: Re: joined-subclass and getting super/sub-class
PostPosted: Tue May 10, 2005 2:47 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
kaared wrote:
I have a class hierarchy that looks like this:
....


I'd be interested to see the complete mapping. I'm having trouble visualizing how you manage to join the Manager to both the EMPLOYEE and PERSON tables.


Top
 Profile  
 
 Post subject: Re: joined-subclass and getting super/sub-class
PostPosted: Tue May 10, 2005 3:47 pm 
Beginner
Beginner

Joined: Wed Feb 09, 2005 3:27 pm
Posts: 29
pksiv wrote:
I'd be interested to see the complete mapping. I'm having trouble visualizing how you manage to join the Manager to both the EMPLOYEE and PERSON tables.


Sure, here's the full mapping for all four entities:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test">
  <class name="Person" table="PERSON" polymorphism="explicit">
    <id name="id" column="person_id" type="integer"/>
    <property name="firstName" column="FIRST_NAME" type="string"/>
    <property name="lastName" column="LAST_NAME" type="string"/>
    <joined-subclass name="Customer" table="CUSTOMER">
      <key column="CUSTOMER_ID" />
      <property name="creditRating" column="CREDIT_RATING" type="integer"/>
      <set name="purchases" lazy="true" inverse="true">
        <key column="CUSTOMER_ID"/>
        <one-to-many class="Purchase"/>
      </set>
    </joined-subclass>
    <joined-subclass name="Employee" table="EMPLOYEE">
      <key column="EMPLOYEE_ID" />
      <property name="hireDate" column="HIRE_DATE" type="date"/>
      <joined-subclass name="Manager" table="MANAGER">
        <key column="MANAGER_ID"/>
        <property name="title" column="TITLE" type="string"/>
      </joined-subclass>
    </joined-subclass>
  </class>
</hibernate-mapping>


Basically I did the same for Manager as I did for Employee. Hibernate solves this very nicely (except for the issues I'm having with being unable to have persons that have multiple roles).

-Kaare


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 10, 2005 4:18 pm 
Beginner
Beginner

Joined: Wed Feb 09, 2005 3:27 pm
Posts: 29
Quote:
I was not talking about performance problems but more about data consistency problems, in the case that a parent attribute is overriden at the subclass level.


I can't really think of a use case for the example you describe, but I know what you're getting at. For my current scenario, overriding values is not a concern since each subclass only adds to the base class, i.e. only person-related fields are persisted in the PERSON table and only customer-related fields are persisted in the CUSTOMER table, so there really should not be any conflict.

It seems that Hibernate doesn't like the idea of having more than one instance with the same identifier, e.g. two instances of Employee both with EMPLOYEE_ID = 1. That makes perfect sense since it's redundant. However, having a Person instance with PERSON_ID = 1 is different from having an Employee instance with EMPLOYEE_ID = 1 (they both *represent* the same person, though). And a Customer instance with CUSTOMER_ID = 1 is also different from the same Employee instance. Now, if I have Person(1) and Employee(1) it should not be unreasonable for me to change either instance and commit the changes to the database. Of course, changes to one instance will invalidate the other, but this is fairly common (i.e. that another application changes the shared data store so that another cache/instance is out of sync and needs to be updated).

Not being able to retrieve the base class does not make any sense whatsoever and I'd really like to understand why Hibernate is unable to accomodate what I'm trying to do, and if this was a conscious design decision. For now it looks like I'll have to implement this without using inheritance. Which is really too bad. :-/

I'll let you know if I find a better way. :-)

Thanks,

-Kaare


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