web-dev-qa-db-ja.com

Hibernateのエンティティがダーティかどうかを確認するにはどうすればよいですか?

Hibernateのエンティティがダーティ状態かどうかを確認するにはどうすればよいですか?つまり一部のフィールドが変更された場合にのみ、UpdatedByUpdatedAtを設定します。だから私は2つのオブジェクトの各フィールドを比較して手動でオブジェクトチェックを行うことができますが、それを行うためのいくつかのよりエレガントな方法があるかもしれませんか?

また、オブジェクトのフィールドを以前と同じ値に設定した場合、Hibernateはエンティティdirtyを作成しますか?つまり:

String name = myEntity.getName()
myEntity.setName(name);

編集:

しかし、別の問題もあります-ネストされたコレクションを持つエンティティがあるため、そのコレクションの要素のみを変更した場合、そのコレクションを所有するオブジェクトではなく、そのコレクション要素のみにUpdatedByを設定します。カスケード操作で更新します。

22
MyTitle

優れた質問ですが、これは短い答えです:Hibernate-SessionにはisDirty()メソッドがあります

例の長い回答(テストケース1):

Hibernateの上でSeam/POJO/JPAを使用している場合。 entityManager.flush()を呼び出す前に、エンティティがダーティであることを知りたい-つまり、Hibernateがupdate-statementを発行するエンティティを知って-これらのレコードに変更を適用します(レコードを変更した人などの値を設定します)。 。

hibernate-SessionにはisDirty()メソッドがあることは知っていますが、これでは十分でない場合もあります。

あなたはpersistence.xml-fileにHibernate-Interceptorを登録できます

     <property name="hibernate.ejb.interceptor" value="path.to.MyInterceptor" />  

そして、メソッドonFlushDirty(...)をインターセプトしてダーティオブジェクトをマップに保存しますが、後でこのマップにアクセスするにはどうすればよいですか?実行時にインターセプターにアクセスできないため(interceptor.getDirtyEntities()を呼び出すことができるように)、次のようになります。

public class MyInterceptor extends EmptyInterceptor {  
         private Map<IdentityKey,Object> dirtyEntitiesMap = new HashMap<IdentityKey,Object>();  

     @Override  
     public boolean onFlushDirty(Object entity, Serializable id,  
               Object[] currentState, Object[] previousState,  
               String[] propertyNames, Type[] types) {  

           dirtyEntitiesMap.put(new IdentityKey(id, entity.getClass()), entity);    
           return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);  
     }  
...  
}  

このテストケースを解決する:エンティティを更新するだけでよい場合、どのエンティティが変更されるかを知る必要はありません。 @PreUpdateメソッドにコードを追加(変更したユーザーを設定)できます。ダーティなエンティティはそれに応じて変更され、更新するものがないため、このメソッドが呼び出されないエンティティはHibernateによって検出されます。 @PrePersistメソッドで新しいエンティティに対して同じことを行うことができますが、これはおそらく同じです。同じメソッドに両方のアノテーションを付けることができます。

変更されたフィールドも記録する必要がある場合は、最初にEnversを確認することをお勧めします。

8
tomj0101

onFlushDirty(...)メソッドは、ダーティコレクションをチェックするために機能します。ネストされたコレクションを持つ親エンティティはonFlushDirtyに渡されますが、渡されたエンティティがコレクション要素である可能性があることは知りませんでした。それを見つけたら、ネストされたコレクションとその親エンティティの両方で機能しました。

public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)

別のメソッドonCollectionUpdate(...)もダーティコレクションをキャッチするために使用でき、onFlushDirty(...)の後に呼び出されます。

0