Hibernate Envers:リスニング操作

なぜこれが必要なのですか?



エンタープライズ開発では、多くの場合、いくつかのテーブルの編集プロセスを追跡する必要があります。

システムにドキュメントがあるとしましょう。 その後、誰かが彼のシリーズを変更しました。 それから数。 その後、彼はタイプをロシア連邦のパスポートから外国に変更しました。 ドイツのパスポート。 変更履歴を追跡し、たとえば、ミスを犯したユーザーのヘッダーをタップできるようにしたいと思います。







何を使用しますか?


システムがHibernateを介してデータベースを操作するという事実から進めます。 この場合、すばらしい録音リスニングメカニズムEnversにアクセスできます。



最後に何が得られますか?


Enversは、変更を追跡する各テーブルに対して、監査テーブルで何かをするたびにレコードを置く追加のプレートを作成します。 例:



テーブルドキュメント(DOCUMENT):

ID シリーズ NUMBER
1 1000 100,000




ドキュメントの監査テーブル:(DOCUMENT_AUD)



ID REV REVTYPE シリーズ NUMBER
1 1 0 1000 100,000
1 2 1 1345 100,000




表からわかるように、id = 1のドキュメントには2つのリビジョンがあります。1つ(REVTYPE = 0)は新しく追加されたレコードで、2つ目はレコードの変更です。 1000シリーズは1345になりました。



さて、あなたは言うが、これはいつ起こったのか? Enversは、デフォルトでREVINFOと呼ばれる別のテーブルを生成します。 リビジョン番号とタイムスタンプが含まれています。 ただし、フィールドの数は拡張できます。



離陸するには何が必要ですか?


ライブラリからは、休止状態自体以外は必要ありません。



persistence.xmlに次の行を追加する必要がありますが、それらが必要な理由は誰もが理解していると思います。



<property name="hibernate.ejb.event.post-insert" value="org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.post-update" value="org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.post-delete" value="org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.pre-collection-update" value="org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.pre-collection-remove" value="org.hibernate.envers.event.AuditEventListener" /> <property name="hibernate.ejb.event.post-collection-recreate" value="org.hibernate.envers.event.AuditEventListener" />
      
      







エンティティを監査する必要があることを示すには、次のように監査可能注釈を指定する必要があります。



 @Entity @Audited public Document
      
      







クラスに従ってスキームを生成する場合、監査テーブルを追加するには、hbm2ddlを起動するantiskタスクのクラス名を変更する必要があります。



 classname="org.hibernate.tool.ant.EnversHibernateToolTask"
      
      







したがって、バージョンプレートとこれらのリビジョンのタイムテーブルがあります。 しかし、このテーブルを少し拡張して別の名前を付けたい場合はどうでしょうか? @RevisionEntityアノテーションは急いで助けてくれます。



エンティティを定義します。



 @Entity @org.hibernate.envers.RevisionEntity(RevisionListener.class) public class RevisionEntity extends DefaultRevisionEntity { }
      
      







ここのDefaultRevisionEntityは、既にタイムスタンプとリビジョン番号が含まれているデフォルトのエンティティです。 何かを再定義したい場合、これを行うことができます:



 @Entity @RevisionEntity(ExampleListener.class) public class ExampleRevEntity { @Id @GeneratedValue @RevisionNumber private int id; @RevisionTimestamp private long timestamp; ... }
      
      







@RevisionNumberと@RevisionTimestampは1回しか使用できないため、DefaultRevisionEntityから継承する場合、2回目に使用することはできません。



私たちの本質を補完する方法は? 他のように!



 @Entity @org.hibernate.envers.RevisionEntity(RevisionListener.class) public class RevisionEntity extends DefaultRevisionEntity { @ManyToOne private User user; // ,  }
      
      







しかし、問題は次のとおりです。この追加データはいつ配置されるのでしょうか? これを行うには、RevisionListenerが必要です。 これはorg.hibernate.envers.RevisionListenerを実装する特定のクラスであり、1つのメソッドがあります。



public void newRevision(Object revision);







監査対象のエンティティ(ドキュメント)が変更されたときに呼び出されます。 ここのリビジョンオブジェクトはRevisionEntityです。 のようなものを書くことができるように



 RevisionEntity revisionEntity = (RevisionEntity) revision; revisionEntity.setUser(...); //  -   , 
      
      







しかし、データを読み取る方法は?




監査テーブル(Document_AUD)にマップされるエンティティがないため、通常のクエリを作成できません。 しかし、Enversはあなたの助けになります。 この表を読むには、AuditQueryが必要です。 次のように取得できます。



 AuditQuery query = AuditReaderFactory.get(em).createQuery();
      
      







それでは、特定のリビジョンまたはリビジョンのリストを正確に言う必要があります。



 query.forRevisionsOfEntity(Document.class, false, false);
      
      







ここではフラグが非常に重要です。 それらの最後が真である場合、クエリは削除されたレコードも返します。

ただし、2番目のフラグは戻り値を制御します。 trueの場合、リビジョン自体のみがリストに含まれます。 そうでない場合は、3つの要素の配列で構成されるリストが返されます。



最初はリビジョン、2番目はRevisionEntity、3番目はリビジョンのタイプです。



たとえば、メインエンティティのIDによって、このクエリにさまざまなフィルタリングを添付できます。



 query.add(AuditEntity.id().eq(docId))
      
      







または、RevisionEntityのパラメーターに従って:



 query.add(AuditEntity.revisionProperty("user_id").eq(userId))
      
      







しかし、現在(hibernate 3.6.1-3.6.4)この機能は動作しません。 バグのためです



さて、最後に、リストを取得します。



 List<Object []> resultList = query.getResultList();
      
      







監査戦略




クエリの効率のために、ValidityAuditStrategyを使用することをお勧めします。 この戦略は、_AUDテーブルに別のフィールドを追加します-REVEND。 したがって、最大のリビジョンを取得するためにネストされた選択を行う必要はありません。



有効にするには、persistence.xmlに行を追加するだけです。



  <property name="org.hibernate.envers.audit_strategy" value="org.hibernate.envers.strategy.ValidityAuditStrategy"/>
      
      







参照:



Hibernate envers



これは、発行を依頼されたhabrayuzer dzigoroによる記事です。



All Articles