5

動作があいまいおよび/または危険な場合のHibernateマッピングの質問。カスケード削除孤立条件とコレクション内のアイテムを制限するwhere条件を持つ1対多の関係があります。ここでのマッピング-

<hibernate-mapping>
 <class name="User" table="user" > 

  <!-- properties and id ... -->

   <set table="email" inverse="true" cascade="all,delete-orphan" where="deleted!=true">
      <key column="user_id">
      <one-to-many class="Email"/>
   </set>

 </class>
</hibernate-mapping>

ここで、1つ以上のEメールオブジェクトに関連付けられているUserオブジェクトがあり、そのうちの少なくとも1つが削除されたプロパティの「true」値を持っているとします。Userオブジェクトでsession.delete()を呼び出すと、次の2つのうちどれが発生しますか?

  1. ユーザーと、deleted=trueを持つオブジェクトを含むすべてのEメールオブジェクトが削除されます
  2. 削除されたユーザーとEメールオブジェクト!=nullが削除されます。

一方では、シナリオ1)はwhere条件を無視しますが、これはドメインモデルによっては正しくない可能性があります。ただし、シナリオ2)では、親が削除され、子(電子メール)テーブルの結合キーに外部キー制約がある場合、削除コマンドは失敗します。どちらが起こり、なぜですか?これは、Hibernateの機能があいまいになる可能性があることを示すもう1つの例ですか?

4

1 に答える 1

4

私はマッピングをテストしませんでしたが、私の意見では、正しい(デフォルトの)動作は、where条件を無視し、すべての子レコードを削除することです(これは、親を削除するときにFK制約違反を回避する唯一のオプションです)。これはビジネスの観点からは「正しく」ないかもしれませんが、他のオプションも機能しないため「正しく」ありません。

要約すると、マッピング自体は一貫性がないように見えます。操作をカスケードしないdelete(そして子の削除をEmail手動で処理する)べきではありません。

または、これが最も正しい動作である可能性があると思います。とに関連付けられたの両方のソフト削除を実装する必要があります。このようなもの:UserEmail

<hibernate-mapping>
  <class name="User" table="user" where="deleted<>'1'"> 

    <!-- properties and id ... -->

    <set table="email" inverse="true" cascade="all,delete-orphan" where="deleted<>'1'">
      <key column="user_id">
      <one-to-many class="Email"/>
    </set>
    <sql-delete>UPDATE user SET deleted = '1' WHERE id = ?</sql-delete>
  </class>

  <class name="Email" table="email" where="deleted<>'1'"> 

    <!-- properties and id ... -->

    <sql-delete>UPDATE email SET deleted = '1' WHERE id = ?</sql-delete>
  </class>
</hibernate-mapping>

ここで行われること:

  • sql-delete実際の削除(ソフト削除)の代わりにフラグを更新するために、デフォルトの削除をオーバーライドします。
  • whereソフト削除されていないエンティティのみをフェッチするために、を使用してエンティティと関連付けをフィルタリングします。

これは、Hibernateアノテーションを使用したソフト削除に触発されています。ただし、テストされていません。

参考文献

于 2010-08-12T22:12:26.557 に答える