8

我有一个表,其中一个字段可以根据描述符值(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

4 回答 4

9

鉴别器用于将类层次结构存储在单个表中。你所拥有的是一个具有多种含义的类。

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

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

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

您需要定义多个 AdminNote 子类,每个子类对应一个鉴别器值。

于 2008-10-06T16:28:31.997 回答
1

鉴别器为整数

通常,如果在子类中将鉴别器值指定为整数,则会出现错误

无法使用 (...) 将鉴别器值 'TYPE' 格式化为 SQL 字符串

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

<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>
于 2010-07-07T12:23:31.527 回答
0

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

试试下面的映射。这里的超类映射本身是抽象的。子类使用相同的 Java 类和每个子类的实体名称。您可能需要将实体名称放入超类映射。但是,我个人会为每个子类映射使用单独的 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>
于 2009-07-10T12:48:02.390 回答
0

与其尝试使用继承功能来获取对正确类的引用,不如考虑使用<any/>映射类型note_type来确定object_id引用的类型,从而将noteObject值设置为正确的对象引用。

有关详细信息<any/>,请参阅NHibernate文档中的“任何类型映射”和博客文章NHibernate 映射

于 2009-08-28T21:16:23.920 回答