如何在 Spring Boot 中使用 Envers 在审计 table 中添加字段

How to add fields in audit table using Envers in Spring Boot

早上好,如何在审计中添加字段table?

我需要审计一些table,但我需要得到执行操作的用户。我将接受审计的实体是:

@Entity
@Table(name ="TableName")
@Audited
@AuditTable("TableNameAuditedLog")
public class MyEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "myId")
    private Long id;

    @Column(name = "myName")
    private String name;
}

查看文档,我看到了一个自定义示例 class 作为我的审计和侦听器,所以我这样做了:

@Data
@RevisionEntity(AuditListener.class)
@MappedSuperclass
public class Audit {

    @Id
    @GeneratedValue
    @RevisionNumber
    private Long id;

    @RevisionTimestamp
    private Long timestamp;

    @Column(name = "user")
    private String user;
}

public class AuditListener implements RevisionListener {

    @Override
    public void newRevision(Object revisionEntity) {
        Audit audit = (Audit) revisionEntity;
        audit.setUsuario("user");
    }
}

我试图在我的实体 class 中扩展我的审计 class,但我对 JPA 有问题,问题是:

Caused by: org.hibernate.MappingException: Unable to find column with logical name: myId in org.hibernate.mapping.Table(TableNameAuditedLog) and its related supertables and secondary tables

我该怎么做?

谢谢大家

从审计中删除 MappedSuperClass class。您还可以让 Audit 扩展 DefaultRevisionEntity。您在 Audit class 中所拥有的只是您的自定义字段。

@Column(name = "user")
private String user;

自定义审计修订实体:

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@RevisionEntity(UserRevisionListener.class)
public class AuditRevisionEntity extends DefaultTrackingModifiedEntitiesRevisionEntity {
  private static final long serialVersionUID = 1L;
  
  private Long userId;
  
  @Column(length = 100, nullable = false)
  private String initiator;
}

和修改监听器

public class UserRevisionListener implements RevisionListener {
  private static final String SYSTEM_USER = "System";
  private transient final SecurityUtils securityUtils;
  
  public UserRevisionListener(final SecurityUtils securityUtils) {
    this.securityUtils = securityUtils;
  }
  
  @Override
  public void newRevision(Object revisionEntity) {
    final AuditRevisionEntity are = (AuditRevisionEntity) revisionEntity;
    
    securityUtils.getPrincipal().ifPresentOrElse((appPrincipal) -> {
      are.setUserId(appPrincipal.getUserId());
      are.setInitiator(appPrincipal.getDisplayName());
    }, () -> are.setInitiator(SYSTEM_USER));
  }
}

在我的例子中,我使用 SecurityUtils 帮助程序获取当前主体(我正在使用具有额外字段的自定义主体)并根据需要设置 AuditRevisionEntity。 Quartz 作业进行了一些更改,因此没有主体,在这种情况下仅设置了启动器。