Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate mappings with a discriminator

Tags:

hibernate

I have a table with one field that can point to a foreign key in one of 3 other tables based on what the descriminator value is (Project, TimeKeep, or CostCenter. Usually this is implemented with subclasses, and I am wondering if what I have below will work. Note the subclass name is the same as the parent class and the noteObject property is mapped to an instance variable of type java.lang.Object so it should accept either a Project, TimeKeep or CostCenter object as long as we cast to the correct type. Will hibernate allow this? Thanks.

<hibernate-mapping package="com.tlr.finance.mappings">

 <class name="AdminNotes" table="admin_notes">
    <id name="adminNoteId" column="admin_note_id" type="integer">
      <generator class="identity" />
    </id>

<discriminator column="note_type" type="string" />

<!-- make this property an enumerated type.  It is the discriminator -->
<property name="adminNoteType" column="note_type" type="string" not-null="true" />
<property name="adminNote" column="note" type="string" not-null="true" />
<property name="adminNoteAdded" column="note_date" type="timestamp"
  not-null="true" /> 

<subclass name="AdminNotes" discriminator-value="project" >
  <many-to-one name="noteObject" column="object_id" class="PsData" /><!-- Project -->
</subclass>

<subclass name="AdminNotes" discriminator-value="user" >
  <!-- rename timekeep to user -->
  <many-to-one name="noteObject" column="object_id" class="Timekeep" /><!-- user -->
</subclass>

<subclass name="AdminNotes" discriminator-value="costCenter" >
  <!-- rename timekeep to user -->
  <many-to-one name="noteObject" column="object_id" class="CostCenter" /><!-- cost center -->
</subclass>

  </class>

</hibernate-mapping>
like image 336
Mike Pone Avatar asked Oct 06 '08 15:10

Mike Pone


2 Answers

Discriminators are used for storing class hierarchies in a single table. What you have there is a single class with multiple meanings.

http://docs.jboss.org/hibernate/core/3.5/reference/en-US/html/mapping.html#mapping-declaration-discriminator

The element is required for polymorphic persistence using the table-per-class-hierarchy mapping strategy and declares a discriminator column of the table. The discriminator column contains marker values that tell the persistence layer what subclass to instantiate for a particular row.

I don't think you'll be able to use a single AdminNote class for each of those different meanings. The discriminator is used at the database level to help distinguish one subclass from another - it's not actually part of the java object model.

You'll need to define multiple subclasses of AdminNote, one for each discriminator value.

like image 145
skaffman Avatar answered Sep 21 '22 20:09

skaffman


Discriminator as integer

Normally, if you specify the discriminator-value as integer in subclass, you get the error

Could not format discriminator value 'TYPE' to SQL string using the (...)

If you wish to use the discriminator as an integer value, you need to first of all specify it for the base class as an integer by setting the discriminator-value attribute in the class element:

<class name="AdminNotes" table="admin_notes" abstract="true" discriminator-value= "-1">

This replaces the default behavior where the discriminator is a class name when a value is not found.

<hibernate-mapping package="com.tlr.finance.mappings">

    <class name="AdminNotes" table="admin_notes" abstract="true" discriminator-value= "-1">
        <id name="adminNoteId" column="admin_note_id" type="integer">
            <generator class="identity" />
        </id>
        <discriminator column="note_type" type="integer" />

        <!-- Make this property an enumerated type. It is the discriminator. -->
        <property name="adminNoteType" column="note_type" type="string" not-null="true" />
        <property name="adminNote" column="note" type="string" not-null="true" />
        <property name="adminNoteAdded" column="note_date" type="timestamp"
                  not-null="true" />

        <subclass name="AdminNotes" discriminator-value="0" entity-name="project">
            <many-to-one name="noteObject" column="object_id" class="PsData" /><!-- Project -->
        </subclass>

        <subclass name="AdminNotes" discriminator-value="1" entity-name="user">
            <!-- Rename timekeep to user -->
            <many-to-one name="noteObject" column="object_id" class="Timekeep" /><!-- user -->
        </subclass>

        <subclass name="AdminNotes" discriminator-value="2" entity-name="costCenter">
            <!-- Rename timekeep to user -->
            <many-to-one name="noteObject" column="object_id" class="CostCenter" /><!-- cost center -->
        </subclass>
    </class>
</hibernate-mapping>
like image 44
Damian Leszczyński - Vash Avatar answered Sep 18 '22 20:09

Damian Leszczyński - Vash