Составной ключ гибернации

Нужно ли, чтобы составной идентификатор был сопоставлен с классом?

это может быть так?

<composite-id>
  <key-property=..../>
  <key-property=..../>
</composite-id>

или должен быть

<composite-id class=....>
  <key-property=..../>
  <key-property=..../>
</composite-id>

если это необходимо, что если у нас есть составной ключ, то этот класс должен реализовать equals() а также override() метод?

3 ответа

Hibernate должен уметь сравнивать и сериализовать идентификаторы. Таким образом, класс идентификатора должен быть сериализуемым и переопределять hashCode() и equals() в соответствии с представлением базы данных о равенстве составного ключа.

Если у вас есть составной идентификатор, сопоставленный как свойства сущности, сама сущность является идентификатором.

Второй подход называется сопоставленным составным идентификатором, в котором свойства идентификатора, названные внутри элемента <композитный-идентификатор>, дублируются как в постоянном классе, так и в отдельном классе идентификатора.

Наконец, составной идентификатор может быть классом компонента. В этом случае класс компонента является идентификатором класса.

Обратите внимание, что настоятельно рекомендуется иметь идентификатор отдельного класса. В противном случае у вас будут только очень неуклюжие способы поиска вашего объекта с помощью session.get() или session.load().

Соответствующие разделы справочной документации:

В этом примере составной идентификатор отображается как свойства объекта. (Ниже предполагается, что вы определяете класс Employee).

<composite-id>
    <key-property name="EmployeeNumber"/>
    <key-property name="Dependent"/>
</composite-id>

class EmployeeAssignment implements Serializable
{
    string getEmployeeNumber()
    void setEmployeeNumber( string value )
    string getDepartment()
    void setDepartment( string value )
    boolean equals( Object obj )
    int hashCode()
}

Составной составной идентификатор:

<composite-id class="EmployeeAssignmentId" mapped="true">
    <key-property name="EmployeeNumber"/>
    <key-property name="Dependent"/>
</composite-id>

class EmployeeAssignment
{
    string getEmployeeNumber()
    void setEmployeeNumber( string value )
    string getDepartment()
    void setDepartment( string value )
}

class EmployeeAssignmentId implements Serializable
{
    string getEmployeeNumber()
    void setEmployeeNumber( string value )
    string getDepartment()
    void setDepartment( string value )
    boolean equals( Object obj )
    int hashCode()
}

Компонент как составной идентификатор:

<composite-id name="Id" class="EmployeeAssignmentId">
    <key-property name="EmployeeNumber"/>
    <key-property name="Dependent"/>
</composite-id>

class EmployeeAssignment
{
    EmployeeAssignmentId getId()
    void setId( EmployeeAssignmentId value )
}

class EmployeeAssignmentId implements Serializable
{
    string getEmployeeNumber()
    void setEmployeeNumber( string value )
    string getDepartment()
    void setDepartment( string value )
    boolean equals( Object obj )
    int hashCode()
}

Оба возможны. Если вы используете

<composite-id>
  <key-property=..../>
  <key-property=..../>
</composite-id>

Тогда не требуется отдельный класс для представления ключа. Значения идентификатора берутся из свойств самого объекта.

Если вы используете

<composite-id class="....">
  <key-property=..../>
  <key-property=..../>
</composite-id>

Тогда указанный класс будет использоваться в качестве держателя для ключевых свойств. Однако класс сущности также должен иметь эти свойства - значения хранятся как в классе сущности, так и в классе составного идентификатора. Класс сущности не знает о классе ключа. Не очень приятно, на мой взгляд.

Существует более приятный третий подход, описанный в документации здесь:

<composite-id name="id" class="OrderLineId">
    <key-property name="lineId"/>
    <key-property name="orderId"/>
    <key-property name="customerId"/>
</composite-id>

Здесь составной ключ представлен классом OrderLineIdэкземпляр которого хранится в поле id в классе сущности. Это сохраняет разделение между сущностью и ключом намного чище.

Если у вас есть составной ключ, который содержит отношения с другими объектами, сделайте это следующим образом:

<composite-id>
    <key-many-to-one name="employee" column="FK_EMPLOYEE" entity-name="net.package.name.Employee" />
    <key-many-to-one name="department" column="FK_DEPARTMENT" entity-name="net.package.name.Department" />
</composite-id>
Другие вопросы по тегам