11.7.6. クエリ
11.7.6.1. 監査情報の読み出し
概要
Hibernate Envers はクエリより監査情報を読み出しする機能を提供します。このトピックではクエリの例を取り上げます。
注記
監査されたデータのクエリは相関サブセレクトが関与するため、多くの場合で
live
データの対応するクエリよりも大幅に処理が遅くなります。
例11.33 特定のリビジョンでクラスのエンティティーをクエリする
このようなクエリのエントリーポイントは次の通りです。
AuditQuery query = getAuditReader() .createQuery() .forEntitiesAtRevision(MyEntity.class, revisionNumber);
AuditEntity
ファクトリクラスを使用して制約を指定することができます。以下のクエリは、name
プロパティーが John
と同等である場合のみエンティティーを選択します。
query.add(AuditEntity.property("name").eq("John"));
以下のクエリは特定のエンティティーと関連するエンティティーのみを選択します。
query.add(AuditEntity.property("address").eq(relatedEntityInstance)); // or query.add(AuditEntity.relatedId("address").eq(relatedEntityId));
結果を順序付けや制限付けしたり、凝集 (aggregations) および射影 (projections) のセット (グループ化を除く) を持つことが可能です。以下はフルクエリの例になります。
List personsAtAddress = getAuditReader().createQuery() .forEntitiesAtRevision(Person.class, 12) .addOrder(AuditEntity.property("surname").desc()) .add(AuditEntity.relatedId("address").eq(addressId)) .setFirstResult(4) .setMaxResults(2) .getResultList();
例11.34 特定クラスのエンティティーが変更された場合のクエリリビジョン
このようなクエリのエントリーポイントは次の通りです。
AuditQuery query = getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true);
前の例と同様に、このクエリへ制約を追加することが可能です。このクエリに以下を追加することも可能です。
AuditEntity.revisionNumber()
- 監査されたエンティティーが修正されたリビジョン番号の制約や射影、順序付けを指定します。
AuditEntity.revisionProperty(propertyName)
- 監査されたエンティティーが修正されたリビジョンに対応するリビジョンエンティティーのプロパティーの制約や射影、順序付けを指定します。
AuditEntity.revisionType()
- リビジョンのタイプ (ADD、MOD、DEL) へのアクセスを提供します。
クエリ結果を必要に応じて調整することが可能です。次のクエリは、リビジョン番号 42 の後に
entityId
ID を持つ MyEntity
クラスのエンティティーが変更された最小のリビジョン番号を選択します。
Number revision = (Number) getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true) .setProjection(AuditEntity.revisionNumber().min()) .add(AuditEntity.id().eq(entityId)) .add(AuditEntity.revisionNumber().gt(42)) .getSingleResult();
リビジョンのクエリはプロパティーを最小化および最大化することも可能です。次のクエリは、特定エンティティーの
actualDate
値が指定の値よりは大きく、可能な限り小さいリビジョンを選択します。
Number revision = (Number) getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true) // We are only interested in the first revision .setProjection(AuditEntity.revisionNumber().min()) .add(AuditEntity.property("actualDate").minimize() .add(AuditEntity.property("actualDate").ge(givenDate)) .add(AuditEntity.id().eq(givenEntityId))) .getSingleResult();
minimize()
および maximize()
メソッドは制約を追加できる基準を返します。最大化または最小化されたプロパティーを持つエンティティーはこの基準を満たさなければなりません。
クエリ作成時に渡されるブール変数パラメーターは 2 つあります。
selectEntitiesOnly
- このパラメーターは明示的な射影が設定されていない場合のみ有効です。true の場合、クエリの結果は指定された制約を満たすリビジョンで変更されたエンティティーの一覧になります。false の場合、結果は 3 つの要素アレイの一覧になります。最初の要素は変更されたエンティティーインスタンスになります。2 番目の要素はリビジョンデータが含まれるエンティティーになります。カスタムエンティティーが使用されていない場合は
DefaultRevisionEntity
のインスタンスになります。3 つ目の要素アレイはリビジョンのタイプ (ADD、MOD、DEL) になります。 selectDeletedEntities
- このパラメーターは、エンティティーが削除されたリビジョンが結果に含まれなければならない場合に指定されます。true の場合、エンティティーのリビジョンタイプが
DEL
になり、id 以外のすべてのフィールドの値がnull
になります。
例11.35 特定のプロパティーを修正したエンティティーのクエリリビジョン
下記のクエリは、
actualDate
プロパティーが変更された、指定の ID を持つ MyEntity
のすべてのリビジョンを返します。
AuditQuery query = getAuditReader().createQuery() .forRevisionsOfEntity(MyEntity.class, false, true) .add(AuditEntity.id().eq(id)); .add(AuditEntity.property("actualDate").hasChanged())
hasChanged
条件を他の基準と組み合わせることができます。次のクエリは、revisionNumber 生成時に MyEntity
の水平スライスを返します。これは、prop1
は修正され、prop2
は修正されなかったリビジョンに限定されます。
AuditQuery query = getAuditReader().createQuery() .forEntitiesAtRevision(MyEntity.class, revisionNumber) .add(AuditEntity.property("prop1").hasChanged()) .add(AuditEntity.property("prop2").hasNotChanged());
結果セットには revisionNumber よりも小さい番号のリビジョンも含まれます。これは、このクエリが「
prop1
は修正され、prop2
はそのままの revisionNumber で変更された MyEntities
をすべて返す」とは読み取られないことを意味します。
次のクエリは
forEntitiesModifiedAtRevision
を使用してこの結果がどのように返されるか表しています。
AuditQuery query = getAuditReader().createQuery() .forEntitiesModifiedAtRevision(MyEntity.class, revisionNumber) .add(AuditEntity.property("prop1").hasChanged()) .add(AuditEntity.property("prop2").hasNotChanged());
例11.36 特定のリビジョンで修正されたクエリエンティティー
次の例は、特定のリビジョンで変更されたエンティティーに対する基本的なクエリになります。読み出される特定のリビジョンで、エンティティー名と対応する Java クラスを変更できます。
Set<Pair<String, Class>> modifiedEntityTypes = getAuditReader() .getCrossTypeRevisionChangesReader().findEntityTypes(revisionNumber);
org.hibernate.envers.CrossTypeRevisionChangesReader
からもアクセスできる他のクエリーは以下のとおりです。
List<Object> findEntities(Number)
- 特定のリビジョンで変更 (追加、更新、削除)されたすべての監査されたエンティティーのスナップショットを返します。
n+1
個の SQL クエリを実行します (n
は指定のリビジョン内で変更された異なるエンティティークラスの数になります)。 List<Object> findEntities(Number, RevisionType)
- 変更タイプによってフィルターされた特定のリビジョンで変更 (追加、更新、削除) されたすべての監査されたエンティティーのスナップショットを返します。
n+1
個の SQL クエリを実行します (n
は指定のリビジョン内で変更された異なるエンティティークラスの数になります)。 Map<RevisionType, List<Object>> findEntitiesGroupByRevisionType(Number)
- 修正操作 (追加、更新、削除など) によってグループ化されたエンティティースナップショットの一覧が含まれるマップを返します。
3n+1
個の SQL クエリを実行します (n
は指定のリビジョン内で変更された異なるエンティティークラスの数になります)。