EJB 3.0(Public Draft)入門記 Java Persistence API Chapter2 その5
今日はリレーションシップについてです。このあたりはPersistence APIのなかでも肝だと思ってます。以前Hibernateで簡単なプログラムをつくろうとしてリレーションシップの定義の仕方がよくわからなくて大変でした。印象としてはルールが多いように感じています。
ところで、アノテーションで指定できるリレーションシップについて疑問に思っていることがあります。それは、アノテーションでのリレーションシップの指定はデータベース上での外部制約参照の設定と必ず対応していなければいけないのか、それともそうではないのかです。最近少しADO.NETを触りましたが、ADO.NETのDataSetの場合、DataSet内のテーブル間のリレーションシップの定義はデータベース上の外部制約参照の定義と一致しなくてもいいようになっています。つまり、データベース上の定義ではリレーションがなくても、DataSet内のDataTable間では自由にリレーションシップやカスケードを定義することができます。Persistence APIもそれと同じでDBの定義から離れてJavaエンティティ間だけのリレーションなどが定義できるんでしょうか?
いずれ実験してみたいと思います。
2.1.7 Entity Relationships
エンティティ間のリレーションシップには次の4つがあります。- one-to-one
- one-to-many
- many-to-one
- many-to-many
リレーションシップはポリモーフィックらしいです。うーん、リレーションシップがポリモーフィックというのはどういうことなんでしょう。なんとなくわかるようでわからない。
リレーションシップそれぞれに対してアノテーションが用意されています。
- OneToOne
- OneToMany
- ManyToOne
- ManyToMany
そのままだ。これらのアノテーションはRDBのスキーマモデリングの一般的な方法を反映しているそうです。
リレーションシップには双方向と単方向があります。双方向のリレーションシップには所有側(owning side)と非所有側(inverse side)があります。単方向のリレーションシップには所有側のみがあります。所有側によってデータベース内のリレーションシップの更新が決定されるそうです。
双方向のリレーションシップには次のルールが適用されます。
- 双方向リレーションシップの非所有側はOneToOneやOneToManyや
ManyToOneManyToManyアノテーションのmappedBy要素を使って所有側を参照する必要がある。 - one-to-manyやmany-to-oneの双方向のリレーションシップのmany側が所有側になる必要がある。したがってManyToOneアノテーションにmappedBy要素が指定されることはありえない。
- one-to-oneの双方向のリレーションシップでは、所有側が外部キーをもつサイドに一致する。
- many-to-manyの双方向のリレーションシップではどちらが所有側になってもよい
リレーションシップのアノテーションにcascade=REMOVEを指定するには制約があってOneToOneかManyToOneOneToManyとして定義されている関連に対してのみ使われるべきだそうです。他の関連(ManyToOneとManyToManyのことだと思う)にcascade=REMOVEを適用するアプリケーションは移植性がないらしいです。
移植性がないということですが、たとえば移植性がなくてもいいからとOneToManyでcascade=REMOVEを指定した場合どうなっちゃうのでしょうか?上の説明を読むとManyの側が所有側で所有側が更新の決定をするはずなんですよね。そのときOneToManyでcascade=REMOVEとあっても意味ないような?
追記 2005/10/29
上記、間違えていたので直しました。リレーションシップのあたりは理解が甘いので1度整理しないといけないなー。
上記のリレーションシップのアノテーションに以外に、たとえばカラムやテーブルのマッピングアノテーションを指定してDefaultのマッピングをオーバーライドしたり細かく指定したりできるそうです。具体例として単方向のone-to-manyマッピングに外部キーのマッピングを使うことができるそうです。Defaultのマッピングについては次節の2.1.8で説明されてます。
マッピングのオーバーライドは指定されているリレーションシップのアノテーションに矛盾しないようにしなければいけないそうです。たとえば、many-to-oneのリレーションシップマッピングが指定された場合、リレーションシップの外部キーにユニークキー制約をつけることは認められていないらしいです。そのようなスキーマレベルのマッピングアノテーションはリレーションシップの所有側に指定しなければいけないとあります。
よくわからないなぁ。所有側に指定しなければいけないっていうけどmany側が所有側になるならmany-to-oneのアノテーションをもっているほうが所有側になるはずで、説明がしっくりこないです。
永続性プロバイダはリレーションシップに関するO/Rマッピングを扱います。そのO/Rマッピングには次のが含まれるそうです。
- エンティティクラスのメタデータの定義に従ったロードやストア
- データベースの定義(たとえば外部キー制約によるもの)に従った参照整合性
2.1.7はここまで。ちょっと理解が浅いです。次回からは例が結構豊富にあるようなのでそれに期待したいところ。次回は 2.1.8 Relationship Mapping Defaultからです。