<composite-id
name="propertyName"
class="ClassName"
mapped="true|false"
access="field|property|ClassName">
node="element-name|."
<key-property name="propertyName" type="typename" column="column_name"/>
<key-many-to-one name="propertyName class="ClassName" column="column_name"/>
......
</composite-id>
複合キーのあるテーブルに対し、識別子プロパティとしてクラスの複数のプロパティをマッピングすることができます。 <composite-id> 要素は、子要素として <key-property> プロパティマッピングと <key-many-to-one> マッピングを受け入れます。
<composite-id>
<key-property name="medicareNumber"/>
<key-property name="dependent"/>
</composite-id>
複合識別子の等価性を実装するためには、永続クラスが equals() と hashCode() をオーバーライド しなければなりません 。 また Serializable も実装しなければいけません。
残念ながら複合識別子のためのこの方法は、永続オブジェクトが自身の識別子であることを意味しています。オブジェクト自身を識別子とする以外に便利な「扱い方」はありません。複合キーに関連した永続状態を load() 出来るようになる前に、永続クラス自身をインスタンス化し、識別子プロパティを設定しなければなりません。 組み込みの 複合識別子と呼ばれるこのアプローチは、本格的なアプリケーションには向いていません。
2つ目の方法は マップされた 複合識別子と呼ばれるもので、 <composite-id>エレメント内で指定した識別プロパティが永続クラスと分離した識別子クラスの両方に重複して存在します。
<composite-id class="MedicareId" mapped="true">
<key-property name="medicareNumber"/>
<key-property name="dependent"/>
</composite-id>
この例では、複合識別子クラス( MedicareId )とエンティティクラス自身の両方が、 medicareNumber と dependent という名前のプロパティを持ちます。識別子クラスは、 equals() と hashCode() をオーバライドし、 Serializable を実装しなくてはなりません。この方法には、明らかにコードが重複するという不都合があります。
次の属性はマッピングした複合識別子を指定するために使用します:
mapped (オプション、デフォルトは false ): マッピングした複合識別子が使用されることと、包含されたプロパティのマッピングが、エンティティクラスと複合識別子クラスの両方を参照することを示します。
class (オプション、ただしマッピングした複合識別子には必須): 複合識別子として使用するクラス。
3つ目のさらに便利な方法は、複合識別子を 項8.4. 「複合識別子としてのコンポーネント」 のコンポーネントクラスとして実装することです。下で記述している属性は、この代替方法にのみ適用されます:
name (オプション、このアプローチでは必須): 複合識別子を保持するコンポーネントタイプのプロパティ(9章を参照してください)。
access (オプション - デフォルトは property ): Hibernate がプロパティの値にアクセスするために使用すべき戦略。
class (オプション - デフォルトはリフレクションにより決定されるプロパティの型): 複合識別子として使われるコンポーネントのクラス(次の節を見てください)。
この3つ目の方法は 識別子コンポーネント と呼び、ほとんどすべてのアプリケーションに対して推奨する方法です。