-->
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: Single table - multiple classes
PostPosted: Tue Jul 19, 2005 5:32 pm 
Newbie

Joined: Tue Jul 19, 2005 4:15 pm
Posts: 4
Location: Utah, USA
I am trying to map a legacy database. I have a Person table that needs to be broken up into a hierarchy with Person as the base class and Patient, Doctor as subclasses that inherit from Person. The problem is that it is possible for a Patient to also be a Doctor. I have tried using a discriminator column, but that doesn't work if the column can't just be a 1 for Patient and 2 for Doctor because it could also be a 3 for Patient and Doctor:

Code:
<class name="Person" ...>
     <discriminator column="EntityRole" ... />
     ...
     <subclass name="Doctor" discriminator-value="1"...>...</subclass>
     <subclass name="Patient" discriminator-value="2"... />...</subclass>
     <!-- what about discriminator-value="3" which is the case when the Person is a Doctor and a Patient? -->
</class>


The Person table has columns IsPatient and IsDoctor, and I added a computed column to act as the discriminator column that gives me a 1, 2 or 3 depending on the values in the IsPatient and IsDoctor columns.

My question: is there a standard practice for how this is done? All of the data for the Person class/interface, Doctor class, and the Patient class comes from the Person table and I need to map it into a hierarchy. I can't use a simple discriminator to tell me if it's a Patient or if it's a Provider, because I want to be able to do an HQL query to retrieve Providers, but, that would only return the ones that are Providers and not also a Patient. Any help here?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 8:06 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
The answer to your question depends of the way your classes are hierarchized; I know that Person is the base class and that Patient and Doctor inherit from Person. But when you say that a Patient to also be a Doctor, how is it done ? If you have a class PatientAndDoctor that inherit from Patient and Doctor, then you can map it with discriminator-value="3" :)

* Are you sure that you should use <subclass>? (because it is for table-per-subclass strategy). <joined-subclass> is for table-per-hierarchy (like your example seems to show) :idea:

* Your columns IsPatient and IsDoctor are useless if you have EntityRole

* I can't use a simple discriminator to tell me if it's a Patient or if it's a Provider ???

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 6:28 pm 
Beginner
Beginner

Joined: Wed Jun 01, 2005 3:22 pm
Posts: 38
Location: Menlo Park, CA
Get rid of Patient. Any Person (employees, retirees, Doctors, etc.) is a potential patient anyhow. Doctor is a subclass of Person.

Of course, this could leave out other details of your environment.


The most important thing to remember when working with any ORM and a legacy DB is that you cannot cleanly map relationships that don't exist. The Relational model is not a 1:1 map to the OO world. Inheritance does not exist in the Relational world. If you are designing the schema with OO in mind, it can be simulated. However, if you're working with a legacy DB, don't force it.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 21, 2005 6:58 pm 
Beginner
Beginner

Joined: Wed Jun 01, 2005 3:22 pm
Posts: 38
Location: Menlo Park, CA
You know what. I've come to a different conclusion.

What you have is an improper OO design, despite the fact that it's a lot like the canonical Person/Employee or Dog/Labrador example we were all taught in school. Doctor/Patient/Person is not an inheritence relationship, which is why you're having trouble modeling it as such.

Instead, you are dealing with 100% Person objects and Person either has an IsDoctor flag or IsInRole(Roles.Doctor) method.

Likewise with IsPatient, but IsPatient() may be a method which queries whether or not they have ever had any appointments.

If you model Doctor as a sublcass of Person, what happens when...

Patient J. Smith has an appointment with Dr. B. Coole.
Dr. B. Coole later loses his medical license and is no longer a Doctor.
Someone looks up the appointment history of J. Smith.
Your code tries
Code:
Doctor doc = session.Get(typeof(Doctor), Appointment.DoctorID);
// or more likely the equivalent is done behind the scenes when you lookup
// Appointment.Doctor


And *poof*! your app is borken.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 23, 2005 7:25 pm 
Newbie

Joined: Tue Jul 19, 2005 4:15 pm
Posts: 4
Location: Utah, USA
Thanks for the replies. I am excited to have a community to help me think about the relationships that I'm trying to model and to be able to leverage your experience.:D

First, let me respond to the issue of the OO design. My approach in the past has come from a database perspective (my experience/positions have dictated such), but, that creates issues for the non-database developers because the objects end up looking funny. I agree with rponton's conclusion not to get rid of the Patient class. If I were an the customer (developer) to use these classes, what would I want them to look like. Forget about the database and what should the hierarchy look like and what should the classes act like? The answer is easy because I have other developers telling me what they don't want the classes to look like. So, we keep the hierarchy of Patient and Doctor inherit from Person.

This also brings us to the conclusion that there shouldn't be a PatientAndDoctor class. It's just not right logically. So, the suggestion to map it with Discriminator-value="3" is not going to work.

Sorry to shoot down those ideas, but, I think what I have come up with seems to be similar to KPixel's suggestion about trying to use <joined-subclass> (I don't think I see how I could implement this though). So, what I have done is map the Person object as it was before. What I changed is I mapped all of the properties for a Person directly onto the Patient and Doctor classes.
Code:
<class name="Patient" where="IsPatient='T'"...>
     ...
     <!-- Person properties -->
     <property name="FirstName"...>
     ...
     <!-- Patient properties -->
     <property name="PrimaryCarePhysician"...>
</class>


The only problem with this method is that I have to explicitly map the IsPatient property and explicitly set this property in my code before saving the object out. But, now I can do queries like "from Patient" and it automatically hydrates the parent class Person. It works, but, there's got to be a better way. :?:

Is there a way to do it with the <joined-subclass> even though the entire hierarchy comes from the same table?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 29, 2005 2:25 pm 
Beginner
Beginner

Joined: Wed Jun 01, 2005 3:22 pm
Posts: 38
Location: Menlo Park, CA
I still think you're taking the wrong approach to the issue.

The problem is not DB vs. OO. The problem is that it's a bad OO design. You're using Inhertiance to represent Roles. And golly gee, you're running into problems modeling what happens when people have multiple roles or when they gain or lose roles.

This is not an inheritance relationship. This is a roles relationship.


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.