Red Hat Training

A Red Hat training course is available for Red Hat JBoss Web Server

8.5. Components as Composite Identifiers

You can use a component as an identifier of an entity class. Your component class must satisfy certain requirements:
  • It must implement java.io.Serializable.
  • It must re-implement equals() and hashCode() consistently with the database's notion of composite key equality.

Note

In Hibernate3, although the second requirement is not an absolutely hard requirement of Hibernate, it is recommended.
You cannot use an IdentifierGenerator to generate composite keys. Instead the application must assign its own identifiers.
Use the <composite-id> tag, with nested <key-property> elements, in place of the usual <id> declaration. For example, the OrderLine class has a primary key that depends upon the (composite) primary key of Order.
<class name="OrderLine">
    
    <composite-id name="id" class="OrderLineId">
        <key-property name="lineId"/>
        <key-property name="orderId"/>
        <key-property name="customerId"/>
    </composite-id>
    
    <property name="name"/>
    
    <many-to-one name="order" class="Order"
            insert="false" update="false">
        <column name="orderId"/>
        <column name="customerId"/>
    </many-to-one>
    ....
    
</class>
Any foreign keys referencing the OrderLine table are now composite. Declare this in your mappings for other classes. An association to OrderLine is mapped like this:
<many-to-one name="orderLine" class="OrderLine">
<!-- the "class" attribute is optional, as usual -->
    <column name="lineId"/>
    <column name="orderId"/>
    <column name="customerId"/>
</many-to-one>

Note

The <column> tag is an alternative to the column attribute everywhere.
A many-to-many association to OrderLine also uses the composite foreign key:
<set name="undeliveredOrderLines">
    <key column name="warehouseId"/>
    <many-to-many class="OrderLine">
        <column name="lineId"/>
        <column name="orderId"/>
        <column name="customerId"/>
    </many-to-many>
</set>
The collection of OrderLines in Order would use:
<set name="orderLines" inverse="true">
    <key>
        <column name="orderId"/>
        <column name="customerId"/>
    </key>
    <one-to-many class="OrderLine"/>
</set>
The <one-to-many> element declares no columns.
If OrderLine itself owns a collection, it also has a composite foreign key.
<class name="OrderLine">
    ....
    ....
    <list name="deliveryAttempts">
        <key>   <!-- a collection inherits the composite key type -->
            <column name="lineId"/>
            <column name="orderId"/>
            <column name="customerId"/>
        </key>
        <list-index column="attemptId" base="1"/>
        <composite-element class="DeliveryAttempt">
            ...
        </composite-element>
    </set>
</class>