Составной ключ гибернации
Нужно ли, чтобы составной идентификатор был сопоставлен с классом?
это может быть так?
<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>