3

ユーザーが実行した結果、対応するテーブルが変更されたアクションを監査しようとしています。たとえば、ユーザーが 2 つのアカウント間で送金を行う場合、次の一連のイベントが生成されます。

  1. 送金テーブルに送金金額を挿入する
  2. 口座 1 の残高表の残高から送金金額を差し引きます。
  3. アカウント 2 のバランス テーブルの残高に送金金額を追加します。

すべてのテーブルの親監査メッセージは次のようになります。

これは、次のスキーマで実現されます

代替テキスト http://img48.imageshack.us/img48/7460/auditloggingiv6.png

問題は、休止状態でこれをどのように表現するかです。

私は以下を作成しました:

In Balance and Transfer のマッピング ファイル

<set name="auditRecords" table="TransferAuditRecord" inverse="false" cascade="save-update">
  <key>
    <column name="AuditRecordID" not-null="true" />
  </key>
  <one-to-many class="audit.AuditRecord"/>
</set>

Transfer クラスと Balance クラスは、メソッドを持つ IAuditable を実装します。

public void setAuditRecords(Set<AuditRecord> auditRecord);
public Set<AuditRecord> getAuditRecords();

AuditRecord のマッピング ファイルには次のものがあります。

<many-to-one name="parentAuditRecord" lazy="false"
             column="parent_id"
             class="audit.AuditRecord"
             cascade="all" />

次に、AOP と Hibernate Interceptors を使用する Logging クラスで、次のことを行います。

AuditRecord auditRecord = new AuditRecord();
auditRecord.setUser(userDAO.findById(
    org.springframework.security.context.SecurityContextHolder.getContext()
        .getAuthentication().getName()));

auditRecord.setParentAuditRecord(getCurrentActiveServiceRecord());

auditable.getAuditRecords().add(auditRecord);

次に、サービス クラスで、次のメソッドをトランザクションに含めて呼び出します。

save(balance1);
save(balance2);
transfer.setPassed(true);
update(transfer);

parentAuditRecord は AOP を使用してスレッド セーフ スタックで作成され、AuditRecordType_id はメソッドの注釈を使用して設定されます。

転送テーブルの「合格」列を省略しました。以前は、save(transfer) を呼び出して、転送金額を Transfer テーブルに挿入し、passed を false に設定していました。(このアクションも監査されます)。

私の要件は、上記の例よりも少し複雑です:P

したがって、上記の一連のイベントは次のようになります。

  1. 転送テーブルの更新
  2. AuditRecord (親) に挿入
  3. AuditRecord に挿入 (子)
  4. TransferAuditRecord への挿入
  5. バランス表に挿入
  6. AuditRecord に挿入 (子)
  7. BalanceAuditRecord に挿入
  8. バランス表に挿入
  9. AuditRecord に挿入 (子)
  10. BalanceAuditRecord に挿入

ただし、上記で定義したカスケード オプションは update ステートメントで失敗します。Hibernate は多対多テーブルへのレコードの挿入を拒否します (AuditRecord マッピングで unsaved-value="any" であっても)。私は常に多対多テーブルに行を挿入したいので、1 回の転送で以前のイベントをマークする多くの監査レコードが存在する可能性があります。ただし、最新のイベントによって、ユーザーが見たいメッセージが決まります。Hibernate は、多対多テーブルと以前の AuditRecord エントリを更新しようとするか、単に AuditRecord と TransferAuditRecord への挿入を拒否して、TransientObjectException をスローします。

監査メッセージは次のように取得されます。

msg=... + ((AuditRecord) balance.getAuditRecords().toArray()[getAuditRecords().size()-1])
    .getParentAuditRecord().getAuditRecordType().getDescription() + ...;

メッセージは次のようになります。「Username set transfer to pass at 11-Oct-2008」

編集多対多テーブルを明示的にマッピングし(関連付けられたインターフェースを使用)、afterTransactionCompletionで、親監査レコードで保存を呼び出し(保存を子監査レコードにカスケードします)、インターフェースを明示的に保存することにしましたすべての子マッピング テーブル。これは真の監査履歴ではなく、ユーザー アクションを記録する非侵襲的な方法です。後でより完全な監査履歴が必要な場合は、Envers を調べます。

4

2 に答える 2

1

parentAuditRecord と transferauditrecord と balance auditrecord の関係は、1 対多であってはならないようです。あなたが入力した内容を読むと、1 対 1 の関係であるその監査階層のサブクラスの使用状況ごとの表として表示されます。

http://www.hibernate.org/hib_docs/reference/en/html/inheritance.html

JBoss の Envers プロジェクトもチェックしてみてください。

于 2008-11-11T20:40:07.800 に答える
0

デザインレベルでは、挿入のみのデータベースデザインがここで驚異的に機能するようです。

現在の状態を維持したい場合は(きっとそうします)、Hibernateリスナー/インターセプター/イベント(ドキュメントで明確に定義されています:http ://www.hibernate.org/hib_docs)を調べることができます。 / v3 / reference / en-US / html_single /

それ以外の場合は、JBoss Enversを調べたところ、非常に便利なようです。

于 2008-11-20T01:21:15.880 に答える