3

PersonとPreferenceの2つのエンティティがあります。両者の間には多くの関係があります。人と好みの関係はマッピングテーブルに保存されます

CREATE TABLE `person_2_preference` (
`person_id` varchar(32) NOT NULL,
`preference_id` varchar(32) NOT NULL,
`sort_order` int(11) NOT NULL,
 PRIMARY KEY (`person_id`,`preference_id`);

ある人は、以下に示すように、好みの順序付きリストを持っています。

<list  name="preferences" table="person_2_preference" lazy="true" inverse="false" 
        cascade="save-update">
            <key column="person_id" update="false"/>
            <index column="sort_order"/>
            <many-to-many class="com.xx.Preference" column="preference_id" />
        </list>

Javaクラスでは、場合によっては設定を並べ替えたいので、Collections.swap(person.getPreferences()、index、index ++)のようなCollections.swapを実行しています(インデックスがないことを確認するための検証があります範囲外)

個人(personDao.saveOrUpdate(person))を保存すると、主キーが原因で一意の制約違反の例外が発生します。

他にも1対多の順序付けされた関係があり、Collections.swapを使用した再順序付けはうまく機能しますが、これは多多関係の制限ですか?御時間ありがとうございます

4

1 に答える 1

1

問題は、スワップによって混乱する Hibernate の内部ストレージ構造にあると思います。また、Hibernate はリストのオブジェクトを第 1 レベルのキャッシュに保存し、実際にデータベースにある値をどこかに保存して、更新が必要かどうかを判断できるようにします。

リスト内の順序を変更する場合、次の 2 つの更新方法があります。person_id と preference_id を変更せずに sort_order を変更するか、sort_order を変更せずに person_id と preference_id を変更します。スワップの場合、2 番目の方法では、2 つの更新のうち最初の更新の後に一意制約違反が発生します。Hibernate の内部組織に関係するいくつかの理由により、Hibernate は 2 番目の方法で更新を行います。

問題を解決する方法として、(少なくとも) 3 つの異なる可能性があります。

  1. テーブル person_2_preference にシリアルを追加し、このシリアルを主キーにします (Hibernate は 1 つの列のみを持つ主キーを好みます)。私はこれをテストしていません。問題が解決するかどうかは 100% わかりません。

  2. HQL update ステートメントによって手動で更新を行います。

    UPDATE Person2Preference SET sortOrder= :order WHERE personId=:person and preferenceId=:preference

    Person2Perference は、person_2_preference にマップされたクラスです。これは、すべての子オブジェクトに対して行う必要があります。この後evict()、親オブジェクトおよび/または子オブジェクトのいずれかが推奨される場合があります (Hibernate は、この更新後に第 1 レベルのキャッシュを更新しません)。

  3. Hibernate の結果として取得したリスト内の要素を交換しません。このリストを配列リスト (または配列) にコピーし、そのコピーでのみスワップを行います。コピーにはオブジェクトへの参照しかないため、これには多くのメモリは必要ありません。Hibernate オブジェクトでは、ソート順の更新のみを行います。

おそらく解決策 3 を実行します。解決策 1 新しいシリアル番号が他に必要な場合に実行します。

于 2013-01-10T08:21:08.277 に答える