10

現在、Hibernate Envers を使用しています。

削除したいエンティティに関連する監査テーブルのエントリを削除するにはどうすればよいですか? 私のエンティティは他のエンティティと関係がありません。

onPostDeleteカスタムリスナーのメソッドでそれを行う必要があることがわかりました:

import org.hibernate.envers.event.AuditEventListener;
import org.hibernate.event.PostCollectionRecreateEvent;
import org.hibernate.event.PostDeleteEvent;
import org.hibernate.event.PostInsertEvent;
import org.hibernate.event.PostUpdateEvent;
import org.hibernate.event.PreCollectionRemoveEvent;
import org.hibernate.event.PreCollectionUpdateEvent;

public class MyListener extends AuditEventListener {

  ...
  @Override
  public void onPostDelete(PostDeleteEvent arg0) {
    // TODO Auto-generated method stub
    super.onPostDelete(arg0);
  }
  ...

}

ドキュメント、フォーラム、多くのことを読みましたが、理解できません。多分それは不可能です、私にはわかりません。

誰かがこれをやったことがありますか?

4

4 に答える 4

4

わかりました、知りたい人のために、これで50%完了しました。

Hibernate Envers の作成者である Adam Warski に感謝します。

「id」は、名前が何であれ、エンティティの ID の hibernate キーワードです。監査エンティティの場合、ID は複合であり、「originalId」と呼ばれます。試す:

"delete from full.package.name.User_AUD u where u.originalId.id = :userid" 

しかし今、revinfo テーブルの監査テーブルに関連するエントリも削除したいと考えています。

誰かが手がかりを持っているなら、私に知らせてください。

于 2010-05-11T18:46:24.497 に答える
3

これは私には完全に機能しており、ネイティブクエリは必要ありません

AuditQuery aq = auditReader.createQuery()
                   .forRevisionsOfEntity( ErpEmploye.class, true, false);       
 aq.add( AuditEntity.id().eq( employe.getCodeId() ) );
 aq.add( AuditEntity.relatedId("period").eq( erpPeriod.getCodeId() ) );
 List result =  aq.getResultList();//parameters must be added, this call is required
 if (result.size()>0){
    Query query = (Query) PrivateAccessor.invokePrivateMethod( aq, "buildQuery", new Object[0]);
    String queryString = (String) PrivateAccessor.getPrivateField( query, "queryString", true );
    PrivateAccessor.setPrivateField( query, "queryString", queryString.replace("select e__ from", "delete from"), true );
    getDAO().executeQuery(query);//transaction required             
}
于 2014-04-20T15:20:11.420 に答える
2

ID でリビジョンを消去する場合は、ネイティブ クエリを使用して直接 envers テーブルにアクセスできます。リビジョンへの参照を含む 2 つのテーブルがあります。監査テーブルが従来の _AUD サフィックスを使用していると仮定すると、エンティティ テーブル名をプログラムで見つけることができます。

Kotlin で書かれたスニペットを次に示します。

fun getAuditTableName(em: EntityManager, aClass: Class<*>): String {
    return getAuditTableName(em, aClass.name) + "_AUD"
}

fun getEntityTableName(em: EntityManager, aClass: Class<*>): String {
    val session = em.unwrap(Session::class.java) as Session
    val sessionFactory = session.sessionFactory
    val hibernateMetadata = sessionFactory.getClassMetadata(className)
    val persister = hibernateMetadata as AbstractEntityPersister
    return persister.tableName
}

テーブル名がわかったので、テーブル内の行を削除できます。(これを JPA トランザクション ブロックに入れ、必要に応じてコンテンツを置き換え、プロバイダーの SQL を調整します)。したがって、MyEntityClass と myRevisionId が与えられた場合、次のようなことができます。

    val em:EntityManager = getEntityManager()
    val auditTableName = getAuditTableName(MyEntityClass::class.java)

    em.createNativeQuery("delete from `$auditTableName` where REV=${myRevisionId}").executeUpdate()
    em.createNativeQuery("delete from REVINFO where REV=${myRevisionId}").executeUpdate()

リビジョン ID 以外のパラメーターで削除する場合は、entity_AUD テーブルでリビジョン ID を照会し、見つかった行を前述の方法で削除します。

RevisionId は複数のエンティティに関連付けることができ、前のメソッドではすべてのエントリが削除されることに注意してください。単一のエンティティのリビジョンを削除するには、エンティティの ID とエンティティのキ​​ー フィールド名が必要です。

フィールド名を動的に取得するためのコードは次のとおりです。

fun getEntityKeyNames(em: EntityManager, entityClass: Class<*>): List<String> {
    val session = em.unwrap(Session::class.java) as Session
    val sessionFactory = session.sessionFactory
    val hibernateMetadata = sessionFactory.getClassMetadata(entityClass.name)
    val persister = hibernateMetadata as AbstractEntityPersister
    return persister.keyColumnNames.toList()
}
于 2017-11-01T02:05:36.423 に答える
0

関連するエンティティが削除された場合でも、通常、監査エントリは追加されるだけで削除されないため、Envers API がそれをサポートしているとは思いません。

ここで、削除されたエンティティのエントリを本当に削除したい場合 (これは監査の目的に反します)、これを少し遅らせて、削除時にエントリを削除する代わりに、たとえば毎晩、毎日のネイティブ クエリを実行することができます。

于 2010-05-08T13:39:06.723 に答える