hibernate composite key

寵の児 提交于 2019-11-27 03:54:23
Lachlan Roche

Hibernate needs to be able to compare and serialize identifiers. So the identifier class must be serializable, and override hashCode() and equals() consistently with the database's notion of composite key equality.

If you have a composite id mapped as properties of the entity, the entity itself is the identifier.

A second approach is called a mapped composite identifier, where the identifier properties named inside the <composite-id> element are duplicated on both the persistent class and a separate identifier class

Finally, a composite-id may be a component class. In this case the component class is the identifier class.

Note that it is strongly recommended to have the ID a separate class. Otherwise you will have only very awkward ways to lookup your object using session.get() or session.load().

Relevant sections of the Reference Documentation:

In this example, a composite-id is mapped as properties of the entity. (The following assume you are defining the Employee class).

<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()
}

A mapped composite-id:

<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()
}

A component as a composite-id:

<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()
}
skaffman

Both are possible. If you use

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

Then no separate class is required to represent the key. The ID values are taken from the properties of the entity itself.

If you use

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

Then the specified class will be a used as a holder for the key properties. However, the entity class must also have these properties - the values are stored both in the entity class and the composite ID class. The entity class has no knowledge of the key class. Not very nice, in my opinion.

There is a nicer 3rd approach, described in the docs here:

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

Here, the composite key is represented by the class OrderLineId, an instance of which is stored under the field id in the entity class. This keeps the separation between entity and key much cleaner.

If you have a composite key that contains relationships to other entities, do it like this:

<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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!