1

次の問題を達成するために Hibernate (...) を設定する方法を知る必要があります。

双方向 (構成) の 1 対多の関連付けがあります (a.bs は Set オブジェクトで、ba は A オブジェクトです)。DB から「a」をロードし、その「bs」の 1 つを更新すると、saveOrUpdate A のときに Hiernate インターセプト A エンティティが必要になります。

コード:

public class A {
   Set<B> bs = new HashSet<B>();
   // ... other fields and setters/getters
}
public class B {
   A a = null;
   // ... other fields and setters/getters
}

使用事例:

A a = load("idA"); // load A from DB
B b = s.getBById("idB"); // get a B element of A
b.setName("blablabla"); // update a field of B
saveOrUpdate(a); // persist A entity with its Bs (including modified B)

(ミニ) モデルに適切に注釈が付けられているため、変更が実行されます。

問題は、インターセプターがエンティティ B の変更のみを検出し、エンティティ A の変更を検出しないことです。監査情報を更新する必要があるため、A の変更を検出する必要があります。

他の観点は次のとおりです。B を介して A エンティティを取得し、更新する必要があります。実際、BからAを取得できますが、変更は永続化されません...

質問 を単純化すると、インターセプターが B エンティティをインターセプトするときに A エンティティを変更する (日付を設定する) 必要があります。onSave では問題なく動作しますが、onFlushDirty では動作しません。なんで?

これは: B が更新されると、インターセプトされます (onFlushDirty)。onFlushDirty メソッドの本体は、とりわけ、次のことを行います。

b.getA().setLastModifyDate(new Date());

したがって、その瞬間に、セッションに接続されている A エンティティがダーティになる必要があるため、傍受アクションを発生させる必要があります...つまり、 onFlushDirty メソッドを再度呼び出す必要があります。私が間違っている?しかし、いずれにせよ、 A.lastModifyDate を更新する必要があります...そしてこれは起こっていません!!!

次に、アプリケーションの実際の動作を示します。

  1. A オブジェクトを作成します
  2. B オブジェクトを作成し、それを A に関連付けます
  3. A => A.lastModifyDate は正しい日付です ( OK )

  4. A オブジェクトを作成します

  5. B オブジェクトを作成し、それを A に関連付けます
  6. A => A.lastModifyDate は正しい日付です ( OK )
  7. B オブジェクトをロードし、更新して B を永続化します -> A.lastModifyDate は正しい日付です ( OK )

  8. A オブジェクトを作成します

  9. B オブジェクトを作成し、それを A に関連付けます
  10. A => A.lastModifyDate は正しい日付です ( OK )
  11. A オブジェクトを読み込み、その B オブジェクトを更新し、A を永続化します -> A.lastModifyDateが正しい日付ではありません( KO )

  12. A オブジェクトを作成します

  13. B オブジェクトを作成し、それを A に関連付けます
  14. A => A.lastModifyDate は正しい日付です ( OK )
  15. A オブジェクトをロードし、A のフィールドとその B オブジェクトを更新し、A を永続化します -> A.lastModifyDateが正しい日付ではありません( KO )

  16. A オブジェクトを作成し、それを永続化します。

  17. A オブジェクトをロードし、それに新しい B オブジェクトを関連付け、A を永続化します => A.lastModifyDate は正しい日付です ( OK )

  18. A オブジェクトを作成し、それを永続化します。

  19. A オブジェクトをロードし、A のフィールドを更新し、それに新しい B オブジェクトを関連付け、A を永続化します => A.lastModifyDate は正しい日付です ( OK )

何か案が?

ありがとう!

4

3 に答える 3

3

問題を解決するには onCollectionUpdate を使用する必要があります

于 2010-10-13T16:03:42.813 に答える
1

わかりましたので、(コメントで述べたように) 実際のインターセプターを使用している場合、「A ではなく B の変化のみを検出する」という意味がよくわかりません。検出したいものを検出するかどうかは、Interceptor の実装次第です

上記の例を取り上げるとsession.saveOrUpdate(a)、インターセプターのonSave()メソッドを呼び出すと、A と B の両方に対して呼び出されます (b が保存されていると言ったので、おそらくそこにある適切なカスケード設定を想定しています)。もちろん、これは A が実際に変更されている (したがって、ダーティであることが判明した) ことを前提としています。アソシエーションが逆として宣言されていない限り、Bだけを変更しても A はダーティになりません。このような場合、B に対して が呼び出されたときに実行する必要があることを実行するか、現在セッション中のすべてのエンティティに対して呼び出されるメソッドにonSave()フックすることができます。findDirty()ただし、複数回呼び出される可能性があることに注意してください。基本的には、 on ではなく各フラッシュで呼び出されsaveOrUpdate()ます。

于 2009-10-14T19:29:47.707 に答える
0

onFlushDirty を使用して機能させたい場合は、saveOrUpdate(a); の後に手動でセッションをフラッシュする必要があります。これにより、永続オブジェクトの更新が確実に db commit されます。自動フラッシュモードの場合、コミットは別のフラッシュをトリガーし、親エンティティがダーティとして検出されます。それ以外の場合、インターセプターは現在変更されているエンティティのみを保存するため、オブジェクトは保存されません。

子コレクションから親エンティティの監査フィールドを更新する必要がある同様のケースがあります。違いは、私のサービスは、親エンティティを除く子コレクションのリストのみを保存していることです。

于 2012-02-16T11:11:04.467 に答える