1

単純な「ツリー」JPA エンティティを想像してください。

public class TreeItem {
  @OneToMany(mappedBy = "parentItem")
  private List<TreeItem> childItems;
  @ManyToOne
  @JoinColumn(name = "parent_id"
  private TreeItem parentItem;
  @Column
  private String name;
}

現在、これらのエンティティの 1 つがロードされ、Web 層に渡され、更新され、保存操作のために EJB に戻されています。私が気付いたのは、このエンティティがツリー内にどれほど深く存在していても、merge()操作中にSQLコマンドを発行する前にツリー全体がロードされていることです。updateなぜこうなった?カスケード オプションが設定されていないため、このような動作の背後にある理由はわかりません。

更新: はい、返されたエンティティは切り離されており、その状態をデータベース レイヤーと同期する必要があります。それは私が理解していることです。しかし、私が理解していないのは、関係の怠惰を無視して、同期にツリー全体を読み取る必要がある理由です。

4

1 に答える 1

0

仕様がマージ操作を定義する方法は次のとおりです。

エンティティ X に適用されるマージ操作のセマンティクスは次のとおりです。

  • X が切り離されたエンティティである場合、X の状態は同じ ID の既存のマネージド エンティティ インスタンス X' にコピーされるか、X の新しいマネージド コピー X' が作成されます。
  • X が新しいエンティティ インスタンスの場合、新しい管理エンティティ インスタンス X' が作成され、X の状態が新しい管理エンティティ インスタンス X' にコピーされます。
  • X が削除されたエンティティ インスタンスである場合、マージ操作によって IllegalArgumentException がスローされます (またはトランザクション コミットは失敗します)。
  • X が管理対象エンティティである場合、マージ操作では無視されますが、これらの関係がカスケード要素値 cascade=MERGE または cascade=ALL アノテーションで注釈付けされている場合、マージ操作は X からの関係によって参照されるエンティティにカスケードされます。
  • カスケード要素値 cascade=MERGE または cascade=ALL を持つ X からの関係によって参照されるすべてのエンティティー Y について、Y は Y' として再帰的にマージされます。X によって参照されるそのようなすべての Y について、X' は Y' を参照するように設定されます。(X が管理されている場合、X は X' と同じオブジェクトであることに注意してください。)
  • X が X' にマージされたエンティティであり、cascade=MERGE または cascade=ALL が指定されていない別のエンティティ Y への参照がある場合、X' からの同じ関連付けのナビゲーションは、 Y と同じ永続 ID。

持続性プロバイダーは、フェッチされていない LAZY とマークされたフィールドをマージしてはなりません。マージ時にそのようなフィールドを無視する必要があります。

エンティティによって使用されるすべてのバージョン列は、マージ操作中および/またはフラッシュ時またはコミット時に永続化ランタイム実装によってチェックされる必要があります。Version 列がない場合、マージ操作中に持続性プロバイダ ランタイムによって実行される追加のバージョン チェックはありません。

したがって、渡すデタッチされたオブジェクトが遅延参照または null としての parentItem を持っていない限り、デタッチされたインスタンスと同期するには、その状態をデータベースから取得する必要があります。

于 2012-10-05T20:55:33.740 に答える