2

Consider this highly simplified sample of relational data (each table may be involved in one-to-many and many-to-many relationships not shown here):

people
+-------+------+--------+
| name  | born | gender |
+-------+------+--------+
| Alice | 1980 |      F |
| Bob   | 1975 |      M |
| Carl  | 1994 |      M |
| Dot   | 1942 |      F |
+-------+------+--------+

workers                         students
+-------+---------+-------+     +-------+-------------+-------+
| name  | company | since |     | name  | institution | since |
+-------+---------+-------+     +-------+-------------+-------+
| Alice | Soylent |  2003 |     | Alice | Western     |  2001 |
| Bob   | HAL     |  1999 |     | Carl  | Eastern     |  2012 |
+-------+---------+-------+     +-------+-------------+-------+

Some people are workers (Bob), some are students (Carl), some are neither (Dot).
Some are both (Alice).

Mapping to OOP, it would be straightforward to have three classes, like:

class Worker extends Person

class Student extends Person

But that's ok as long as the specialization is disjoint: object alice can't be instance of Worker and Student at the same time. If you get a list of Person objects, you cannot cast the same element to both subclasses.

First of all, is there any specific name for this (likely common) impedance mismatch case?

Next, suppose you can't remodel the schema. I may have my own way to workaround with OOP, but I'm mainly interested in yours. Is there some sort of best-practice guideline?
This example has only two ISA relations, but my impression is, the more non-disjoint sub-entities, the more OOP gets uncomfortable.

3

One way to do this would be to model this in the application using composition:

//maps to the table PEOPLE
class Person
{
   String name;
   Date birthdate;
   GenderEnum gender;

   Worker workerAttributes;
   Student studentAttributes;
}

//maps to the table WORKERS
class Worker
{
   String name;
   String company;
   Date since;
}

//maps to the table STUDENTS
class Student
{
   String name;
   String institution;
   Date since;
}

Each Person object contains an object containing Worker information and Student information. When you populate these objects, you would have to ensure that you've joined to the correct Person.

  • Clean. This is close to what I have in mind... – matpop Nov 14 '14 at 16:03
1

I don't know how it's modeled in your application, but in the real world, people cannot only be both student and worker, they can be workes at different companies at the same time. Now looking closer at the tables shows that they look like N:N join tables, don't they?

So what I would do is rename Student to Enrollment and Worker to Contract. Person now has two N:N relations, one with Institution, and one with Company. In terms of OOP:

class Person {
    Collection<Enrollment> enrollments;
    Collection<Contract> employmentContracts;
} 
  • Ah! You got me Yogu :) You're right, in my example the workers and students tables really look like intermediate tables for many-to-many relations (someone would call them pivot tables) but it was not intentional. Thanks for pointing it out (upvote!). My fault, I should have pointed up that the name column in all the tables must be considered a unique key. I also realize that the example is somewhat oversimplified, so I'm going to edit the question soon and try to improve it. – matpop Nov 15 '14 at 10:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.