0

監査対象のエンティティ A があります。エンティティ A は、フィールド 'name' とエンティティ B のコレクション (多対多の関係として注釈が付けられています) を保持しています。A のインスタンス、定義された名前、エンティティ B のコレクションを作成し、すべてを DB に保存します。これはリビジョン 1 です。次に、Aの名前を変更してDBで更新しました。これはリビジョン 2 です。次のメソッドを使用して、リビジョン #2 でクラス A のすべてのエンティティを取得します

List<A> list = getAuditReader().createQuery().forEntitiesAtRevision(A.class, 2)
    .add(AuditEntity.revisionNumber().eq((int) revisionId)).getResultList();

リビジョン #2 でエンティティ A を取得しますが、Envers はこの A に関連するエンティティ B のコレクションもリビジョン #1 から取得します。Envers で使用されるクエリの例を次に示します。

SELECT a_b_aud.a_id, a_b_aud.b_id
FROM   a_b_aud CROSS JOIN b_aud
WHERE  a_b_aud.b_id=b_aud.id 
       AND b_aud.rev=(SELECT max(b_aud2.rev)) FROM b_aud AS b_aud2 WHERE b_aud2.rev<=2 AND b_aud.id=b_aud2.id)
       AND a_b_aud.rev=(SELECT max(a_b_aud2.rev)) FROM a_b_aud AS a_b_aud2 WHERE a_b_aud2.rev<=2 AND a_b_aud.a_id=a_b_aud2.a_id AND a_b_aud.b_id=a_b_aud2.b_id)

しかし、実際には、リビジョン #2 で変更がなかった場合 (パフォーマンスの問題のため)、エンティティ B のコレクションとして NULL が必要です。

このクエリには 2 つの副選択があります。また、A (C、D、E、F) に関連するエンティティのコレクションが複数あり、b_aud と a_b_aud ごとに約 10 万行ある場合、上記のクエリには多くの時間がかかります。エンティティ B を監査対象外として定義し (つまり、@Audited アノテーションを B に追加しませんでした)、AB 関係を次のように定義しました。

@ManyToMany
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
@JoinTable(name = "a_b", joinColumns = @JoinColumn(name = a_id))
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
public Set<B> getBs();

最初の SUBSELECT を修正します。しかし、要求されたリビジョンが存在しない場合に B を照会しないという標準的な解決策を見つけることができません (私の場合は #2)。したがって、クエリは次のようになります。

SELECT a_b_aud.a_id, a_b_aud.b_id
FROM   a_b_aud CROSS JOIN b_aud
WHERE  a_b_aud.b_id=b_aud.id b_aud.rev=2 AND a_b_aud.rev=2

私が見つけた唯一の解決策は、ネイティブ SQL クエリを使用し、hibernate テンプレートを使用して実行することです。次に、ResultTransformer を使用して結果値をエンティティ A に変換します。

誰でもこの問題を解決できますか? 2 番目の SUBSELECT を回避するために追加する必要がある標準的な構成/注釈はありますか?

4

1 に答える 1

0

Envers には、要求されたときに関連するエンティティを読み込まないというオプションはありません。ただし、B エンティティは(リレーションの注釈に関係なく)常に遅延ロードされるわけではないため、それらをロードするクエリを実行したくない場合は、単にそのフィールドにアクセスしないでください。

より良い読み取りパフォーマンスが必要な場合は、有効性監査戦略も参照してください。 http://docs.jboss.org/hibernate/core/4.1/devguide/en-US/html/ch15.html#d5e4085を参照してください。読み取りは高速ですが、書き込みは低速です。

于 2013-02-08T11:25:49.213 に答える