Отображения гибернации с дискриминатором - PullRequest
8 голосов
/ 06 октября 2008

У меня есть таблица с одним полем, которая может указывать на внешний ключ в одной из 3 других таблиц в зависимости от значения дескриптора (Project, TimeKeep или CostCenter. Обычно это реализуется с помощью подклассов, и мне интересно, то, что я имею ниже, будет работать. Обратите внимание, что имя подкласса совпадает с именем родительского класса, а свойство noteObject сопоставлено с переменной экземпляра типа java.lang.Object , поэтому он должен принимать либо Project, TimeKeep или объект CostCenter, если мы приводим его к правильному типу. Будет ли это разрешено в спящем режиме? Спасибо.

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

9 голосов
/ 06 октября 2008

Дискриминаторы используются для хранения иерархий классов в одной таблице. У вас есть один класс с несколькими значениями.

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

Элемент требуется для полиморфной персистенции используя таблицу для каждого класса иерархии картографическая стратегия и объявляет дискриминатор столбца таблицы. столбец дискриминатора содержит маркер значения, которые говорят о постоянстве слоя какой подкласс создать для конкретный ряд.

Я не думаю, что вы сможете использовать один класс AdminNote для каждого из этих различных значений. Дискриминатор используется на уровне базы данных, чтобы помочь отличить один подкласс от другого - на самом деле он не является частью объектной модели Java.

Вам необходимо определить несколько подклассов AdminNote, по одному для каждого значения дискриминатора.

1 голос
/ 07 июля 2010

Дискриминатор как целое число

Обычно, если вы указываете значение дискриминатора как целое число в подклассе, вы получаете ошибку

Не удалось отформатировать значение дискриминатора 'TYPE' в строку SQL, используя (...)

Если вы хотите использовать дискриминатор в качестве целочисленного значения, вам необходимо прежде всего указать его для базового класса в качестве целого числа, установив атрибутcriminator-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>
0 голосов
/ 29 августа 2009

Вместо того чтобы пытаться использовать возможности наследования для получения ссылки на правильный класс, вам следует рассмотреть возможность использования типа отображения <any/>, где вы используете note_type, чтобы определить тип, на который ссылается object_id и таким образом устанавливая ваше noteObject значение для правильной ссылки на объект.

Подробнее о <any/> см. ' Отображения любых типов ' в документации NHibernate и сообщение в блоге Отображение NHibernate .

0 голосов
/ 10 июля 2009

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...