web-dev-qa-db-ja.com

NHibernate / Hibernate OneToMany関係でinverse = falseを使用する場合

私はHibernateの逆属性を把握しようとしてきましたが、これは概念的に難しいものの1つにすぎないようです。

私が得た要点は、one-to-manyマッピングを使用して子オブジェクトのコレクションを持つ親エンティティ(例:Parent)がある場合、マッピングでinverse = trueを設定すると、Hibernateに「相手側(子)が自身を更新して、テーブル内の外部キー参照を維持する責任がある」ことを伝えます。

これを行うと、コードのコレクションにChildrenを追加し、Parentを(カスケードオールセットで)保存する際に2つの利点があるように見えます: データベースで不必要なヒットを保存します (逆セットがないため、HibernateはFK関係を更新する2つの場所があると考えています)、そして公式ドキュメントによると:

関連付けの列がNOT NULLと宣言されている場合、NHibernateは関連付けを作成または更新するときに制約違反を引き起こす可能性があります。この問題を防ぐには、inverse = "true"とマークされた多くの値の端(セットまたはバッグ)との双方向の関連付けを使用する必要があります。

これはすべてこれまでのところ理にかなっているようです。私が得ないのはこれです:あなたはいつ[〜#〜] not [〜#〜]1でinverse = trueを使用したいですか多対多の関係?

70
James Allen

Matthieuが言うように、inverse = trueを設定したくない唯一のケースは、子が親の知識を持っていない場合など、子が自分自身を更新する責任を負わない場合です。

現実の世界を試してみましょう。不自然な例ではありません:

<class name="SpyMaster" table="SpyMaster" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
  <set name="Spies" table="Spy" cascade="save-update">
    <key column="SpyMasterId"/>
    <one-to-many class="Spy"/>
  </set>
</class>

<class name="Spy" table="Spy" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
</class>

スパイマスターはスパイを持つことができますが、スパイクラスには多対1の関係が含まれていないため、スパイはスパイマスターが誰であるかを知ることはできません。また、(便利なことに)スパイは悪党になる可能性があるため、スパイマスターと関連付ける必要はありません。次のようにエンティティを作成できます。

var sm = new SpyMaster
{
    Name = "Head of Operation Treadstone"
};
sm.Spies.Add(new Spy
{
    Name = "Bourne",
    //SpyMaster = sm // Can't do this
});
session.Save(sm);

そのような場合、smを保存する動作がSpyMasterテーブルとSpyテーブルに挿入され、その後のみSpyテーブルを更新してFKを設定するため、FK列をNULL可能に設定します。この場合、inverse = trueに設定すると、FKは更新されません。

81
Nigel

賛成票が高かったにもかかわらず、私は別の答えを持っています。

次の関係を持つクラス図を考えてみましょう。

 Parent =>アイテムのリスト
 Item => Parent 

誰もeverは、Item => ParentリレーションはParent => Itemsリレーションに対して冗長であるとは言いませんでした。アイテムは任意の親を参照できます。

しかし、アプリケーションでは、関係が冗長であることを知っています。リレーションをデータベースに個別に保存する必要がないことを知っています。そこで、アイテムから親を指す単一の外部キーに保存することにします。この最小限の情報は、リストおよびを参照するために十分です。

これをNHでマップするために必要なことは次のとおりです。

  • 両方の関係に同じ外部キーを使用する
  • nHに、一方(リスト)が他方に対して冗長であり、オブジェクトを保存するときに無視できることを伝えます。 (それが、NHが実際にinverse="true"

これらは逆に関連する考えです。他に何もありません。これは選択肢ではありません。正しいマッピングの方法は1つしかありません。


スパイ問題:これはまったく異なる議論ですifアイテムから親への参照をサポートしたい場合。これはあなたのビジネスモデル次第であり、NHはこれについて何も決定しません。関係の1つが欠落している場合、もちろん冗長性はなく、逆の使用もありません。

Misuse:メモリに冗長性のないリストでinverse = "true"を使用すると、保存されません。もしそこにあるはずの場合、inverse = "true"を指定しないと、NHは冗長な情報を2回保存するかもしれません。

29

単方向の関連付けが必要な場合、つまり、子が親に移動できない場合。その場合、子は親の前に保存されるため、FK列はNULLABLEである必要があります。

15
MatthieuGD