5

次のシナリオを考えます。

@Entity
public class A {
  @OneToMany(mappedBy = "a", cascade = CascadeType.ALL)
  private List<B> bList;
}

@Entity
public class B {
  @ManyToOne()
  @JoinColumn(name = "a_id", referencedColumnName = "id")
  private A a;

  @ManyToOne()
  @JoinColumn(name = "c_id", referencedColumnName = "id")
  private C c;
}

@Entity
public class C {
  @OneToMany(mappedBy="c", cascade=CascadeType.ALL, orphanRemoval=true)
  @CascadeOnDelete // eclipselink specific optimization annotation
  private List<B> bList;
}

つまり、オブジェクトAとオブジェクトCの両方に多数のBオブジェクトが含まれています。

Cオブジェクトを削除するとき(技術的には、複数のCオブジェクトを含むオブジェクトを更新し、orphanremovalを使用しています)、現在のアノテーションで期待どおりに機能する、参照されているすべてのBオブジェクトを削除したいと思います。ただし、エンティティマネージャは、キャッシュ内にあるオブジェクトAが一部の子を失ったことを理解していないようです。Aのインスタンスがある場合は、もちろんそのbListを手動で更新するか、新しいクエリを実行して更新する必要がありますが、新しくフェッチされたAオブジェクトでさえまだ古くなっています。繰り返しますが:

  • Cオブジェクトが削除されます。
  • 削除は、orphanRemovalを使用してBオブジェクトにカスケードされます。
  • エンティティマネージャにキャッシュされているオブジェクトのbListは更新されません
  • エンティティマネージャのキャッシュを手動で削除すると、適切に更新されたオブジェクトが取得されます。

これはどのように解決できますか?エンティティマネージャーが永続コンテキストを自動的に更新するか、@ JoinColumnでカスケードアノテーションを利用できるようにすることを期待しますが、ここではどちらも当てはまらないようです。

編集:問題は、オブジェクトAのbListが更新されたときにオブジェクトCのbListが更新されないことにあるようです(したがって、変更をカスケードできません)。理由はわかりませんが、インスタンス化されたオブジェクトではなく、永続コンテキストについて話していることに注意してください。

4

1 に答える 1

6

JPAは関係の維持を行いません。アプリケーションはそれらを維持する必要があります。つまり、エンティティを削除するたびに、アプリケーションはそのエンティティへの参照をクリーンアップする責任があります。それが外部キー関係である場合は明らかです。データベースの制約が行われない場合、通常は例外が発生するためです。関係に厳密なデータベース制約がない場合でも、逆参照の場合、ユーザーは通常、JPAがそれを処理すると誤って信じており、キャッシュが破損したままになっています。

これを処理する方法は、CおよびBエンティティへの参照を削除することです。オブジェクトモデルでは、これはAのbListを修正してBを削除することを意味します。これは、エンティティの削除イベントまたはアプリケーションコードで処理されるのを見てきました。この場合、Aには外部キーがないため、削除が発生した後(つまり、フラッシュまたはコミット後)に、影響を受けるAエンティティをデータベースから更新することもできます。

于 2011-04-28T14:16:43.720 に答える