Hibernation displays with discriminator

I have a table with one field that can point to a foreign key in one of the three other tables based on the value of the descriptor (Project, TimeKeep or CostCenter. This is usually implemented using subclasses, and I'm interested in what I have below will be Note that the subclass name is the same as the parent, and the noteObject property is mapped to an instance variable of type java.lang.Object , so it must accept either the project, TimeKeep or CostCenter as long as we apply the correct type. Can hibernate allow it? 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> 
+7
hibernate
source share
4 answers

Discriminators are used to store class hierarchies in a single table. You have one class with multiple values.

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

The element is required to maintain polymorphism using the table hierarchy for the mapping strategy class and declares the table discriminator column. the discriminator column contains a marker values ​​indicating the level of preservation which subclass to create for a particular row.

I don’t think you can use one AdminNote class for each of these different values. The discriminator is used at the database level to distinguish one subclass from another - it is not actually part of the java object model.

You will need to define several subclasses of AdminNote, one for each discriminator value.

+8
source share

Discriminator as a whole

Usually, if you specify the discriminator value as an integer in a subclass, you will get an error

Failed to format 'TYPE' discriminator value to SQL string using (...)

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

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

This replaces the default behavior when the discriminator is the class name when the 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> 
+1
source share

AFAIK, you can reuse Java class names for subclass mappings if you use entity names.

Try the following. Here, the mapping of the superclass itself is abstract. Subclasses use the same Java class and entity name for each subclass. You may need to put the entity name in the superclass mapping. However, I would personally use separate Java subclasses for each subclass, since with entity names you would need to provide an entity name when you need to save an object through a Hibernate 3.3.2 session) based on the adminNoteType field.

 <hibernate-mapping package="com.tlr.finance.mappings"> <class name="AdminNotes" table="admin_notes" abstract="true"> <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" entity-name="project"> <many-to-one name="noteObject" column="object_id" class="PsData" /><!-- Project --> </subclass> <subclass name="AdminNotes" discriminator-value="user" entity-name="user"> <!-- rename timekeep to user --> <many-to-one name="noteObject" column="object_id" class="Timekeep" /><!-- user --> </subclass> <subclass name="AdminNotes" discriminator-value="costCenter" entity-name="costCenter"> <!-- rename timekeep to user --> <many-to-one name="noteObject" column="object_id" class="CostCenter" /><!-- cost center --> </subclass> </class> </hibernate-mapping> 
0
source share

Instead of using inheritance to get a reference to the correct class, you should instead use the display type <any/> in which you use note_type to determine the type referenced by object_id , and thereby set noteObject to the correct reference per object.

For more information on <any/> see NHibernate Any Type Mappings and the NHibernate Mapping Blog Post.

0
source share

All Articles