複合キー(Hibernate3)
複合キーのマッピングと,複合キーを外部キーにもつ場合のマッピング方法を調査してみた.
本頁のサンプルでは,以下のテーブルを扱う.
テーブルDetailは複合キー{ID,REGIST_DATE}をもつ.
うちIDはテーブルOutlineを参照する外部キーである.
テーブルMoreDetailは複合キー{ID,REGIST_DATE,SEQ_NO}をもつ.
うち{ID,REGIST_DATE}はテーブルDetailを参照する外部キーである.
Detail(ID, REGIST_DATE) MoreDetail(ID, REGIST_DATE, SEQ_NO,VALUE)この二つのテーブルをそれぞれオブジェクトにマッピングする.
複合キーをもつテーブルDetailのマッピングファイルを以下にしめす.
複合キーの場合は,要素composite-idを使用する.
子要素はkey-many-to-oneか,key-propertyで,複合キーを構成する各要素を記述する.
両者の違いは,前者はさらに外部キーである場合,後者はそうでない場合に使用する.
テーブルDetailの属性IDはテーブルOutlineのIDを参照するので,要素key-many-to-oneである.
今回は,主キーを構成しているOutline.id値とregistDateのミリ秒値にてhashCodeを生成し,それを使用してequalsメソッドを実装した.
<key-many-to-one name="outline" class="Outline" column="ID"/>要素many-to-oneと同じ要領である. テーブルDetailの属性registDateは属性IDとともにテーブルDetailの主キーを構成する.
<key-property name="registDate" column="REGIST_DATE" type="date"/>要素propertyと同じ要領である. 複合キーを使用する場合のhbmファイルの作成の要点は以上であるが,複合キーを使用する場合は,マッピングするクラスが以下の要件つく.
- java.io.Serializableを継承する.
- equalsメソッドを実装する.
- hashCodeメソッドを実装する.
※ equalsメソッドは以下の要件を満たす必要がある.
- 反射律
- (a.equals(a) == true)
- 対象律
- (a.equals(b) == true) → (b.equals(a) == true)
- 推移律
- (a.equals(b) == true) & (b.equals(c) == true) → (a.equals(c) == true)
- equalsがtrueの場合,必ずhashCode()の値は同じ(逆は成立するとは限らない).
- (a.equals(b) == true) → (a.hashCode() == b.hashCode())
- 対象オブジェクトが同じ状態なら(メンバの値に変化がないなら)何度やっても返り値は同じ.
- a.hashCode() == a.hashCode())
Detailは複合キーの一部IDがOutlineを参照していた.
サンプルのもう一つのテーブルMoreDetailの複合キーはDetailのキー,すなわち上記のIDとregistDateを外部キーとしてもつ.
さらにseqNoも複合キーを構成する.
マッピングファイルは以下となる.
複合キーは要素composit-idであることはDetailと同じである.
その子要素の外部キーがさらに複合キーの場合,要素key-meny-to-oneは子要素columnをもつ.
<key-many-to-one name="detail" class="Detail"> <column name="ID"/> <column name="REGIST_DATE"/> </key-many-to-one>これで,属性ID,REGIST_DATEはテーブルDetailを参照すると表現された. キーでなく,通常の複合外部キーの場合も同様である. 上記が主キーの一部でなかった場合,以下のようになる.
<many-to-one name="detail" class="Detail"> <column name="ID"/> <column name="REGIST_DATE"/> </many-to-one>MoreDetailも主キーが複合キーなので,Detailと同様,Serializableの継承,hashCode,equalsメソッドを実装する必要がある.

