O/R Mapping

O/R mapping is quite interesting.  I would like to post this question for discussion.

I have the following classes: Employee, FullTimeStaff, PartTimeStaff, etc.  FullTimeStaff and PartTimeStaff have many attributes and behaviors in common and also many other unique attributes and behaviors.  So, FullTimeStaff inherits from Employee and PartTimeStaff also inherits from Employee.

Do you think it is good to map both FullTimeStaff and PartTimeStaff to a single table called Employee (the table contains an extra field to identity whether he is full time or part time) in the database




Answer this question

O/R Mapping

  • vasudupe

    Hi,

    It's good in case you will not get new types for example offshoreStaff !

    For the sake of extensibility, you just can create a new table to hold the employeeTypes, and make it a parent to the Employees table; so in future if you get any more types it will embrace it!

    Regards,



  • Pavan Contractor

    There is an excellent article discussing this at the URL

    http://www.utexas.edu/its/windows/database/datamodeling/dm/hierarchies.html

    essentially, you will have a database table for each of your classes - with 1-1 relationship between the base class and derived classes. (i.e. the employee ID will be the primary key of all the tables.)

    I am not sure how NHibernate will map it, maybe you need to define the Eployee ID as foriegn key in the tables corresponding to designed classes.

    Regards

    Pranshu



  • silence421

    I have a table keeping all FullTimeStaff and PartTimeStaff and we also have a StaffType field to classify them. I have a staff ID to get a staff but I do not know the staffType until I retrieve staff data from the database. What is the best way to instantiate an object Instatiate it as Employee and then convert it to appropriate Staff Any pattern to do that

  • James Boman

    Inheritance is commonly handled by mapping an entire class hierarchy to a single table. The table would have an extra column indicating what kind of object was saved there - in NHibernate, this is called the "discriminator".

    That way, when you retrieve the object from the database, the O/R mapper knows which class to instantiate.

    From an application perspective, you shouldn't have to cast the object to anything but Employee, seeing as how the subclasses should primarily override the behaviors of the base (domain model style).

    Hope that helps.



  • Ramanakumar

    Pranshu, there is a big problem with that kind of methods (having one table for each class). You have a great OO design and a bad data design, so if you want to use a reporting engine you will have a lot of problems with that approach.



  • BrentB

    Navingp is correct. The point of O/R mapping is to provide a layer of abstraction between the software and the database. Changes to database could be made without affecting your domain model isolating the impact on software to the data access layer and mapping layer. The mapping ties your domain model and the physical database together.

    There are ways to design the database or domain model to make the mapping the layer easier. One way is to have the object model and the data model be the same (no mapping layer is really needed). See Fowler TableModule pattern. However, by making them the same you end up either de-normalizing the database or not follow OO best practices. O/R Mapping also provides a layer of abstraction to isolate the software from database changes.

    Model the objects in your problem domain following the best OO tenants and model the database following standard database normalization patterns. Use the mapping layer to move from each model.


  • Kate Boothby

    Yes, a single table for everything is the model I want to discuss. But I want to go 1 step further, i.e. the pattern I posted earilier is to use a factory class to identify the object type in the table first and then instantiate the object according to this type. I did not use this pattern in real programming. I just think it is theorectically possible. Any one has comment

  • Mike Hildner

    The idea of O-R mapping is to provide a Object Oriented Inteface to Database entities. Typically it should not matter how you map the entity fields inside database as long as the 'O' of the O-R is designed properly. The 'R' needs to be handled as a separate issue while designing your datbase.

    In your example, it would be oaky to map both FullTimeStaff and PartTimeStaff to a single table with a attribute indicating the type.


  • Cam Evenson

    I like that you are "object" thinking, instead of "database" thinking.

    My comment above dealt with how your StaffFactory would save the concrete class it created in the database, and how it would retrieve it later - how it would know that staffId 12345 is a Manager, and create an instance of the appropriate class.



  • Ed.S.

    Converting an object into another is not a good practice. You are not forced to map one object to only one table, a complex object may have data from more than one table. Just be careful to encapsulate the logic you are going to use to create that object.

  • Indigo Cowboy

    Hi Demian,

    I only partly agree with your statement.

    Martin Fowler presents all the three ways of mapping as discussed in different posts.

    In his pattern of Concrete Table Inheritence presents using a class for each concrete class (or each non abstract class)

    http://martinfowler.com/eaaCatalog/concreteTableInheritance.html

    but then he also presents other patterns for mapping the same - having one table per class http://martinfowler.com/eaaCatalog/classTableInheritance.html

    or having a single table for everything http://martinfowler.com/eaaCatalog/singleTableInheritance.html

    In my experience I find singleTableInheritence to be simplest and suported by all OR mapping tools.

    The class Table Inheritence makes sense if the base class has a lot of meat in it ( like the Party parent class in party pattern).

    Concrete table inheritence makes sense when the base class becomes trivial.

    Also I donot believe that the reporting will be difficult to implement for Class Table Inheritence , it might just be sligly slower.



  • RameshK

    Hi Udi

    Perhaps I show you the code in my mind for your comment:

    Public Class StaffFactory
    Private m_ID As Integer

    Public Function CreateStaff(ByVal ID As Integer) As Staff
    m_ID = ID
    Dim aStaff As Staff
    If GetStaffType() = "FullTime" Then
    aStaff = New FullTimeStaff
    Else
    aStaff = New PartTimeStaff
    End If
    loadData(aStaff)
    Return aStaff
    End Function

    Private Function GetStaffType() As String
    Return GetStaffTypeFromDatabase(m_ID)
    End Function

    Private Sub loadData(ByRef s As Staff)
    GetStaffDataFromDatabase(s)
    End Sub
    End Class

    '--------

    Public MustInherit Class Staff
    'Common Property - skip for brevity
    'Common Method - skip for brevity

    MustOverride Function Behavior1() As Integer
    MustOverride Function Behavior2 As String
    ' Other Unique Class functions skip for brevity

    End Class

    '---------
    Public Class FullTimeStaff : Inherits Staff
    Public Overrides Function Behavior1() As Integer
    'Implementation specific to FullTimeStaff
    End Function

    Public Overrides Function Behavior2() As Integer
    'Implementation specific to FullTimeStaff
    End Function
    End Class

    '---------

    Public Class PartTimeStaff : Inherits Staff
    Public Overrides Function Behavior1() As Integer
    'Implementation specific to PartTimeStaff
    End Function

    Public Overrides Function Behavior2() As Integer
    'Implementation specific to PartTimeStaff
    End Function
    End Class



  • Norbert.Bender

    I don't know NHibernate. My initial thinking is as follows:

    1. Create Employee as an abstract class.

    2, Create a StaffFactory class which has a CreateInstance method. The CreateInstance method accepts staffID as parameter and can return object inherited from Employee. The StaffFactory then creates an object based on the StaffType in the database.

    I am not sure it is a correct way but I think it works.



  • Snow Moon

    a employee table with the attributes they have in common a table with employeeTypes and a table with employeeType specific attributes is more extenseble, when you must change or attributes of a type or add some new employeetypes.

  • O/R Mapping