関連マッピング
イントロダクション
関連マッピングはしばしば理解が最も難しいものになります。
この章では、基本的な一つ一つのケースについて述べます。
単方向のマッピングから始め、それから双方向のケースについて考えていきます。
例として、Person と Address を用います。
関連は、結合テーブルを入れるかかどうかと、
多重度によって分類することにします。
すべての例でnot nullの外部キーを使用します。
これはHibernateの要件ではありません。
not null制約を外したとしても、マッピングは問題なく動作します。
単方向関連
多対一
単方向多対一関連 は単方向関連の中で最も一般的なものです。
]]>
一対一
外部キーの単方向一対一関連 はほとんど同じものです。
唯一違うのは、カラムのユニークな制約です。
]]>
主キーの単方向一対一関連 は通常、特別なIDジェネレータを使います。
(この例では関連の方向が逆になっていることに注意してください)
person
]]>
一対多
外部キーの単方向一対多関連 はとても特殊なケースで、
あまり推奨されていません。
]]>
このような関連のために結合テーブルを使うことをお薦めします。
結合テーブルを使った単方向関連
一対多
結合テーブルを使った単方向一対多関連
はより好ましいです。
unique="true" の指定により、多重度が多対多から一対多
に変わったことに注意して下さい。
]]>
多対一
結合テーブルの単方向多対一関連 は
関連が任意であるときに非常に一般的なものです。
]]>
一対一
結合テーブルの単方向一対一関連 は、本当に特殊ですが
不可能ではありません。
]]>
多対多
最後に、単方向多対多関連 を示します。
]]>
双方向関連
一対多/多対一
双方向多対一関連 は最も一般的な関連です。
(標準的な親子関係です)
]]>
List (または他のインデックス付きのコレクション)を使うなら、
外部キーの key カラムを not null に設定し、
コレクション側が各要素のインデックスをメンテナンスするように、
関連を扱う必要があります
(update="false" かつ insert="false"
と設定して、反対側を仮想的にinverseにします):
...
...
]]>
もし外部キーカラムが NOT NULL であるならば、
コレクションマッピングの <key> 要素を
not-null="true" にすることは重要です。
入れ子になった <column> 要素だけではなく、
<key> 要素も not-null="true"
と定義しないようにしてください。
一対一
外部キーの双方向一対一関連 は非常に一般的です。
]]>
主キーの双方向一対一関連 は特殊なIDジェネレータを使います。
person
]]>
結合テーブルを使った双方向関連
一対多/多対一
結合テーブルの双方向一対多関連 です。
inverse="true" が関連端、コレクション、結合のいずれかに
設定できることに注意してください。
]]>
一対一
結合テーブルの双方向一対一関連
は非常に特殊ですが、可能です。
]]>
多対多
最後に、双方向多対多関連 を示します。
]]>
より複雑な関連マッピング
より複雑な関連結合は 極めて 稀です。
マッピングドキュメントにSQL文を埋め込むことで、
さらに複雑な状況を扱うことができます。
例えば、accountNumber, effectiveEndDate,
effectiveStartDate カラムを持つaccount(口座)情報の履歴を扱うテーブルは、
以下のようにマッピングします。
case when effectiveEndDate is null then 1 else 0 end
]]>
そして、関連を 現時点の インスタンス
(effectiveEndDate がnullであるもの)にマッピングします。
以下のようになります:
'1'
]]>
さらに複雑な例では、Employee(従業員) と Organization(組織)
間の関連が Employment(雇用) テーブルで保持される場合を想像してください。
このテーブルには雇用データの履歴がすべて含まれます。
すると従業員の 最も最近の 雇用者を表す関連
(最も最近の startDate を持つもの)は、このようにマッピングできます:
select employeeId, orgId
from Employments
group by orgId
having startDate = max(startDate)
]]>
この機能は非常に強力です。
しかしこのような場合、普通はHQLやcriteriaクエリを使う方がより実践的です。