-->
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.  [ 2 posts ] 
Author Message
 Post subject: Mapping of Multiple Interface Inheritance
PostPosted: Wed Feb 01, 2006 12:41 pm 
Newbie

Joined: Tue Jan 31, 2006 7:17 am
Posts: 2
I'm working on converting a CMS to use NHibernate. The CMS already has a domain model which uses multiple interface inheritance, where each interface is mapped to a database table. To explain what I'm doing, I've developed the following simplified model as an example:

Image

Code:
   
    public class Vehicle
    {
        public int VehicleID;
        public int HorsePower;
    }

    public interface IProduct
    {
        public int ProductID;
        // interface members must be properties
        decimal Price { get; set; }
    }

    public class Car : Vehicle, IProduct
    {
        private decimal _price;
        public decimal Price
        {
            get { return _price; }
            set { _price = value; }
        }
    }

    public class OrderLine
    {
        public IProduct Product;
    }


In this model, there is a Vehicle class, which has sub-class Car. There are also OrderLines, each of which holds a reference to a Product (represented by the interface IProduct).

Cars are also Products, implementing the IProduct interface. This model assumes that there are other Vehicles which aren't Products (e.g. CarTransporter), and that there are other Products which aren't Cars (e.g. Bananas), otherwise the model could be much simpler. For legibility the extra classes aren't shown.

N.b. I'm assuming "table-per-class" mapping is to be used.

The model would be easy to map if there were no Product table in the database. Unfortunately without a Product table the OrderLine table would (presumably?) have to have references into tables representing all subclasses of IProduct (Car, Banana etc.) which it would coalesce when returning its Product property. Using a Product table becomes even more desirable when storing collections of Products etc.

Conversely, when using a Product table we run into the problem that during mapping, the Car class cannot be declared as a joined-subclass of both Vehicle and IProduct.

This seems like a no-win situation, but I've had a go at coming up with a workaround which doesn't affect the public interface presented by the domain model. The solution I've come up with is inelegant, any pointers or alternatives anyone can suggest would be greatly appreciated!

I've come up with the following database design:

Image

The Vehicle-Car hierarchy is mapped using a relationship between their primary keys. I've used a foreign key to relate Product and Car, as using a relationship between the primary keys would mean having to ensure that any non-car Products use IDs that aren't used by Vehicles.

The mappings I've set up are as follows:

Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
  <!-- Vehicle -->
  <class name="Vehicle" table="Vehicle">
    <id name="VehicleID" column="VehicleID">
      <generator class="identity" />
    </id>
    <property name="HorsePower" column="HorsePower" />
    <!-- Car -->
    <joined-subclass name="Car" table="Car">
      <key column="CarID" />
    </joined-subclass>
  </class>
  <!-- Order Line -->
  <class name="OrderLine" table="OrderLine">
    <id name="OrderLineID" column="OrderLineID">
      <generator class="indentity" />
    </id>
  </class>
</hibernate-mapping>


Note the omission of a Product class. To cover products I've added an additional class, ProductReference:

Code:
    public class ProductReference
    {
        public int ProductID

        public Car Car;
        // public Banana Banana;

        public IProduct Item
        {
            get
            {
                if (Car != null)
                    return Car;
                // else if (Banana != null)
                // return Banana;

                return null;
            }
        }
    }


This class represents a reference to a Product and maps directly to the Product table in the database. The item property returns the appropriate sub-class, according to what product is pointed to by the reference. (Its role is quite similar to that of an abstract factory).

The mapping for this class is as follows:

Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
  <!-- ProductReference -->
  <class name="ProductReference" table="Product">
    <id name="ProductID" column="ProductID">
      <generator class="identity" />
    </id>
    <one-to-one name="Car" class="Car" foreign-key="ProductID" />
    <!--<one-to-one name="Banana" class="Banana" foreign-key="ProductID" />-->
  </class>
</hibernate-mapping>


Using this class, I can add a private property/field to OrderLine of type ProductReference and use a Hibernate mapping to instantiate this property using the relationship between the OrderLine and Product tables. The code would look something like this:

Code:
public class OrderLine
{
    //...

    // this field is set by an NHibernate mapping
    private ProductReference _productReference;

    public IProduct Product
    {
        get { return _productReference.Item; }
        set { _productReference.Item = value; }
    }
}


Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
  <!-- ... -->
  <!-- Order Line -->
  <class name="OrderLine" table="OrderLine">
    <id name="OrderLineID" column="OrderLineID">
      <generator class="indentity" />
    </id>
    <many-to-one name="ProductReference" column="ProductID" class="ProductReference" />
  </class>
</hibernate-mapping>


As I said, any suggestions/help would be much appreciated!

Thanks for reading,

morcs


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 02, 2006 12:39 pm 
Newbie

Joined: Tue Jan 31, 2006 7:17 am
Posts: 2
I've discovered the <any> element and "implicit polymorphism", this seems like it might be a solution to allowing multiple interface inheritance (multiple implementation), is this how people are solving the problem?


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