Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Hibernate和AOP审核模式映射_Java_Hibernate_Audit - Fatal编程技术网

Java 使用Hibernate和AOP审核模式映射

Java 使用Hibernate和AOP审核模式映射,java,hibernate,audit,Java,Hibernate,Audit,我试图审核用户执行的导致相应表更改的操作。例如,如果用户要在两个帐户之间转账,这将生成以下事件序列: 将转账金额插入转账表 从科目1的余额表中的余额中减去转账金额 将转账金额添加到科目2的余额表中的余额 所有表的父审核消息将是:“用户生成的金额XXX转账” 这是通过以下模式实现的: 问题是如何在hibernate中表示这一点 我创建了以下内容: 在Balance and Transfer的映射文件中 <set name="auditRecords" table="TransferAud

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

  • 将转账金额插入转账表
  • 从科目1的余额表中的余额中减去转账金额
  • 将转账金额添加到科目2的余额表中的余额
  • 所有表的父审核消息将是:“用户生成的金额XXX转账”

    这是通过以下模式实现的:

    问题是如何在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>
    
    然后在服务类中,我调用事务中包含的以下方法:

    save(balance1);
    save(balance2);
    transfer.setPassed(true);
    update(transfer);
    
    parentAuditRecord是使用带有线程安全堆栈的AOP创建的,AuditRecordType_id是使用方法上的注释设置的

    我遗漏了传输表上的“passed”列。之前,我调用save(transfer)将转账金额插入转账表,并将passed设置为false。(此操作也经过审核)

    我的要求比上面的例子稍微复杂一些:p

    因此,上述事件的顺序应为:

  • 更新传输表
  • 插入到审核记录(父项)
  • 插入到审核记录(子项)
  • 插入到TransferAuditRecord中
  • 插入余额表
  • 插入到审核记录(子项)
  • 插入余额审计记录
  • 插入余额表
  • 插入到审核记录(子项)
  • 插入余额审计记录
  • 但是,上面定义的级联选项在update语句中失败。Hibernate拒绝在多对多表中插入记录(即使AuditRecord映射中未保存的值=“any”)。我总是想在多对多表中插入行,这样一次传输可能会有许多标记以前事件的审计记录。但是,最新事件决定用户希望看到的消息。Hibernate要么尝试更新多对多表和以前的AuditRecord条目,要么干脆拒绝插入AuditRecord和TransferAuditRecord,抛出TransientObject异常

    检索到的审核消息如下所示:

    msg=... + ((AuditRecord) balance.getAuditRecords().toArray()[getAuditRecords().size()-1])
        .getParentAuditRecord().getAuditRecordType().getDescription() + ...;
    
    信息应该这样说: “用户名设置传输于2008年10月11日12:00通过”


    EDIT我决定显式映射多对多表(带有关联的接口),然后在TransactionCompletion中,在父审计记录上调用save(将保存级联到子审计记录),然后在所有子映射表上显式保存接口。这不是真实的审核历史记录,而是记录用户操作的非侵入性方法。如果我以后需要更完整的审计历史记录,我将研究Envers。

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


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

    在设计层面,似乎只有插入式db设计才能在这里发挥作用

    如果您想保持现在的状态(我相信您会这样做),可以查看Hibernate侦听器/拦截器/事件(在文档中定义得很好:)

    除此之外,我刚刚研究了JBoss Envers,它似乎也非常有用

    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);
    
    msg=... + ((AuditRecord) balance.getAuditRecords().toArray()[getAuditRecords().size()-1])
        .getParentAuditRecord().getAuditRecordType().getDescription() + ...;