Monday, April 11, 2011

Legacy mapping with hibernate

For my current project I have to map a legacy database using hibernate, but I'm running into some problems. The database is setup using one 'entity' table, which contains common properties for all domain objects. Properties include (among others) creation date, owner (user), and a primary key which is subsequently used in the tables for the domain objects.

A simple representation of the context is as such:

table entity
 - int id
 - varchar owner

table account
 - int accountid (references entity.id)

table contact
 - int contactid (references entity.id)
 - int accountid (references account.accountid)

My problem exhibits itself when I try to add a collection mapping to my account mapping, containing all contacts belonging to the account. My attempts boil down to the following:

<hibernate-mapping>
    <class name="Contact" table="entity">
     <id name="id" column="id">
      <generator class="native" />
     </id>
     <join table="contact">
      <key column="contactid"/>
      <!-- more stuff -->
      </join> 
    </class>
</hibernate-mapping>

<hibernate-mapping>
    <class name="Account" table="entity">
     <id name="id" column="id">
      <generator class="native" />
     </id>


     <bag name="contacts" table="contact">
      <key column="accountid" />
      <one-to-many class="Contact"/>
     </bag> 

     <join table="account">
      <key column="accountid"/>
      <!-- more stuff -->
     </join>

    </class>
</hibernate-mapping>

However, when I try to fetch the account I get an SQL error, stating that the entity table does not contain a column called accountid. I see why this is happening: the mapping tries to find the accountid column in the entity table, when I want it to look in the contact table. Am I missing something obvious here, or should I approach this problem from another direction?

From stackoverflow
  • This looks to me like you actually need to be mapping an inheritance, using the Table Per Subclass paradigm.

    Something like this:

    <class name="entity" table="entity">
        <id name="id" column="id">
            ...
        </id>
    
        <joined-subclass name="contact" table="contact">
            <key column="contactid"/>
        </joined-subclass>
    
        <joined-subclass name="account" table="account">
            <key column="accountid"/>
        </joined-subclass>
    </class>
    

    That's approximate by the way - it's described in detail in section 9.1.2 of the Hibernate documentation (just in case you can't find it, it's called "Table per subclass").

    Cheers

    Rich

    boutta : Full ack for the inheritance part.
    Erik van Brakel : I'm inclined to accept this answer. However, I'm waiting for more replies first, I hate to accept and then de-accept an answer. +1 at least ;-)

0 comments:

Post a Comment