3

これらの 2 つのエンティティがある場合:

@Entity class A { 
    @OneToOne(cascade = CascadeType.MERGE, mappedBy = "a") B b; 
    //getters+setters
}
@Entity class B { 
    @OneToOne(cascade = CascadeType.MERGE) A a; 
    //getters+setters
}

JPA仕様はこれを保証していますか?

A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
A managedA = entityManager.merge(a);
// after commit, managedA will have a reference to a managed B which JPA implementation will link to managedA instead of original unmanaged A
Assert.assertTrue(managedA.getB().getA() == managedA);

私の理解では、(少なくとも最新の EclipseLink では、少なくとも時々) 動作しますが、仕様ではそれが保証されていません。

反例/仕様の抜粋を歓迎します:-)

4

1 に答える 1

1

そうです、JPA仕様はそれを保証しません。実際、ほとんどの場合、merge() のセマンティクスは、新しいインスタンス (エンティティ マネージャーによって作成され、指定されたオブジェクトの状態がマージされるマネージド インスタンス) を返すというものですが、これは単に単純化したものです。入れたまさにそのオブジェクトをアタッチした場合、メソッドは実際に void を返す可能性があります (persist() メソッドが行うように)。なぜそのように設計されたのかはわかりません。実際には、この異なるセマンティクスを持つのは少し面倒で、アプリケーション コードで目的の動作をカプセル化するのに時間がかかりました。

マージ操作の実際のセマンティクスは、JPA 仕様の最終リリースの 3.2.7.1 Merging Detached Entity State に記載されています。入れたオブジェクトと現在の永続コンテキストに応じて、動作が異なります。

補足: エンティティは、拡張永続コンテキストを使用しない限り、トランザクションが終了するとすぐに切り離されます。

また、通常は == 演算子を使用してオブジェクトを比較すべきではないことに注意してください。これは、実際にはオブジェクト比較に必​​要なセマンティクスではないためです (jvm ID はビジネス オブジェクト ID と等しくありません)。

于 2013-03-15T20:47:53.007 に答える