gpt4 book ai didi

java - 使用 Hibernate 和 AOP 的审计模式映射

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:20:35 24 4
gpt4 key购买 nike

我正在尝试审核用户执行的导致相应表发生更改的操作。例如,如果用户要在 2 个帐户之间转账,这将生成以下事件序列:

  1. 将转账金额插入转账表
  2. 从帐户 1 的余额表中的余额中减去转账金额。
  3. 将转账金额添加到帐户 2 的余额表中。

所有表的父审计消息将是:“用户生成的金额为 XXX 的转帐”

这是通过以下架构实现的: schema

alt text http://img48.imageshack.us/img48/7460/auditloggingiv6.png

问题是我如何在 hibernate 中表示它?

我创建了以下内容:

在 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 拦截器的日志记录类中,我有:

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) 将转账金额插入到转账表中,并将 passed 设置为 false。 (此操作也经过审核)。

我的要求比上面的例子稍微复杂一点:P

所以上面的事件顺序应该是:

  1. 更新传输表
  2. 插入 AuditRecord(父级)
  3. 插入 AuditRecord(子)
  4. 插入 TransferAuditRecord
  5. 插入余额表
  6. 插入 AuditRecord(子)
  7. 插入 BalanceAuditRecord
  8. 插入余额表
  9. 插入 AuditRecord(子)
  10. 插入 BalanceAuditRecord

但是,上面定义的级联选项在更新语句中失败。 Hibernate 拒绝向多对多表中插入记录(即使 AuditRecord 映射上的 unsaved-value="any"也是如此)。我总是想将行插入到多对多表中,因此一个传输可能有许多标记以前事件的审计记录。但是,最新事件决定了用户希望看到的消息。 Hibernate 要么尝试更新多对多表和以前的 AuditRecord 条目,要么它只是拒绝插入 AuditRecord 和 TransferAuditRecord,抛出 TransientObjectException。

审核消息是这样检索的:

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

消息应该是这样的:“用户名设置传输在 2008 年 11 月 11 日 12:00 通过”

编辑 我决定显式映射多对多表(使用关联接口(interface)),然后在 afterTransactionCompletion 中调用父审计记录上的保存(将保存级联到子审计记录)然后显式保存所有子映射表上的接口(interface)。这不是真正的审计历史记录,而是一种记录用户操作的非侵入性方法。如果我稍后需要更完整的审计历史记录,我会查看 Envers。

最佳答案

parentAuditRecord 和transferauditrecord 和balance auditrecord 之间的关系似乎不应该是一对多的。当我阅读您键入的内容时,我将其视为该审计层次结构的每个子类使用情况的一个表,这是一对一的关系。

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

您可能还想查看 JBoss 的 Envers 项目。

关于java - 使用 Hibernate 和 AOP 的审计模式映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/282023/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com