使用鉴别器进行Hibernate映射

时间:2008-10-06 15:25:13

标签: hibernate

我有一个包含一个字段的表,可以根据描述符值(Project,TimeKeep或CostCenter)指向其他3个表中的一个外键。通常这是通过子类实现的,我想知道是否我在下面的内容将起作用。注意子类名称与父类相同,noteObject属性映射到java.lang.Object 类型的实例变量,因此它应该接受一个Project,只要我们转换为正确的类型,TimeKeep或CostCenter对象.hibernate会允许这个吗?谢谢。

<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>

4 个答案:

答案 0 :(得分:9)

判别器用于在单个表中存储类层次结构。你有什么是一个有多重含义的单一课程。

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

  

元素是   多态持久性所必需的   使用table-per-class-hierarchy   映射策略并声明一个   表的鉴别器列。该   鉴别器列包含标记   告诉持久层的值   要为a实例化的子类   特别的一行。

我认为您不能为每个不同的含义使用单个AdminNote类。在数据库级别使用鉴别器来帮助区分一个子类 - 它实际上不是java对象模型的一部分。

您需要定义多个AdminNote子类,每个子类用于每个鉴别器值。

答案 1 :(得分:1)

判别器为整数

通常,如果在子类中将discriminator-value指定为整数,则会出现错误

  

无法使用(...)

将鉴别器值'TYPE'格式化为SQL字符串

如果您希望将鉴别器用作整数值,则首先需要通过在class元素中设置discriminator-value属性将其指定为基类:

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

这取代了在未找到值时鉴别器是类名的默认行为。

<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>

答案 2 :(得分:0)

AFAIK,如果使用实体名称,则可以为子类映射重用Java类名。

尝试下面的映射。这里的超类映射本身就是抽象的。子类对每个子类使用相同的Java类和实体名称。您可能需要将entity-name放入超类映射。但是,我个人会为每个子类映射使用单独的Java子类,因为当您需要通过Session API持久保存对象时,您必须提供实体名称,或者实现实体名称解析。 Tuplizer(Hibernate 3.3.2)基于adminNoteType字段。

<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>

答案 3 :(得分:0)

您应该考虑使用<any/>映射类型,而不是尝试使用继承功能来获取对正确类的引用,而是使用note_type映射类型来确定object_id的类型1}}正在引用,因此将noteObject值设置为正确的对象引用。

有关<any/>的详细信息,请参阅Any type mappings文档中的“NHibernate”和博客文章 NHibernate Mapping