13

私はこれらのエンティティを持っています

class Foo{
    Set<Bar> bars;
}

class Bar{
    Foo parent;
    String localIdentifier;
}

このマッピングでは(申し訳ありませんが、注釈はありません。私は時代遅れです):

<class name="Foo">
    ...
    <set name="bars" cascade="all-delete-orphan" lazy="false" inverse="true">
        <key>...</key>
        <one-to-many class="Bar"/>
    </set>
</class>


<class name="Bar">
    ...
    <property name="localIdentifier" column="local_identifier"/>
    <many-to-one name="parent" column="parent_id" />
</class>

また、2 つの列に一意の制約があります: local_identifierand parent_id(それぞれに一意の制約はありませんが、両方を含む単一の一意の制約です。たとえば、同じ親と同じ localIdentifier を持つ 2 つの行は許可されません)

alter table bar add constraint unique_bar unique (parent_id, local_identifier)

そして、それらを使用するこのコード:

//foo is persistent, foo id = 1
Bars bars = foo.getBars();
bars.clear(); // bars contained 1 item [parent_id = 1, local_identifier = "a"]
Bar newBar = new Bar();
newBar.setParent(foo);
newBar.setLocalIdentifier("a");
bars.add(newBar);

さて、何らかの理由で、Hibernate は呼び出された順序で物事を実行しません。clear()(挿入)の前に(削除)を実行しませんが、add()逆の場合は、最初に挿入を試みて、ConstraintViolationException

少しsession.flush()bars.clear();に を追加すると、これを修正できることはわかっていますが、この場合、醜い方法でセッションにアクセスすることはできません。

それで、フラッシュが唯一の解決策ですか?または、アクションの順序を尊重する Hibernate バージョンはありますか?

更新: ところで、コレクションを逆参照すると、https://www.hibernate.org/117.html#A3から HibernateException が発生します。

I get HibernateException: Don't dereference a collection with cascade="all-delete-orphan"これは、オブジェクトを cascade="all-delete-orphan" コレクションでロードしてから、コレクションへの参照を削除すると発生します。このコレクションを置き換えないでください。孤立削除アルゴリズムが変更を検出できるように、clear() を使用してください。

4

4 に答える 4

8

フラッシングに代わるものはないと思います

ここから:

Hibernate は一意の制約に違反しています!

Hibernate は、一意の制約に関しては外部キーほど賢くありません。場合によっては、ちょっとしたヒントを与える必要があるかもしれません。

2 つのオブジェクトが両方とも更新され、一方が値を「解放」し、もう一方が同じ値を「取得」している場合、一意制約違反が発生する可能性があります。回避策は、最初のオブジェクトを更新した後、2 番目のオブジェクトを更新する前に、手動でセッション をflush()することです。

(この種の問題は、実際にはめったに発生しません。)

于 2010-01-14T16:45:26.487 に答える
1

ここでセッションをフラッシュしたくない場合は、リスト全体を (new List<Bar>()の代わりにClear()) 置き換えてみてください。Hibernate は、新しいアイテムを追加する前に、実際にはすべてのアイテムを一度に削除する必要があります。試してみてください。うまくいくかどうかはわかりません。

于 2010-01-14T16:19:59.843 に答える
1

Oracle を使用している場合は、遅延可能な制約を使用して、トランザクションがコミットされるまで制約のチェックを延期することもできます。これが他のデータベースでサポートされているかどうか、またはどのようにサポートされているかはわかりません。

于 2010-01-20T06:21:00.923 に答える