【问题标题】:Hibernate Envers - include date of when change happenedHibernate Envers - 包括更改发生的日期
【发布时间】:2016-05-27 19:02:38
【问题描述】:

我们刚刚开始使用 Hibernate Envers,它可以很好地记录什么发生了变化,但是,有没有一种方法可以记录何时发生了变化?

那么,它可以在审计表中添加一个日期时间列吗?

根据 Envers 文档,这应该默认发生:

当 Envers 开始一个新的修订时,它会创建一个新的修订实体来存储有关修订的信息。默认情况下,这仅包括

  • 修订号 - 一个整数值(int/Integer 或 long/Long)。本质上是修订的主键
  • 修订时间戳 - long/Long 或 java.util.Date 值,表示进行修订的时刻。使用 java.util.Date 而不是 long/Long 作为修订时间戳时,请注意不要将其存储到会降低精度的列数据类型中。

因此,我的理解是,获取修订时间戳不需要任何必要的操作。但是,就我而言,由 envers 创建的表中没有修订时间戳。

谢谢

【问题讨论】:

标签: java hibernate jpa hibernate-envers


【解决方案1】:

您需要定义一个供 Envers 使用的自定义 RevisionEntity,以便添加所需的属性。有必要对您假装用作自定义修订实体的类进行注释:

@RevisionEntity(AuditingRevisionListener.class)

在这个实体中,您可以定义您需要的内容。例如,这应该是一个很好的起点:

@Entity
@Table(name = "DATA_REVIEW_TABLE")
@RevisionEntity(AuditingRevisionListener.class)
public class AuditedRevisionEntity {
  @RevisionNumber
  @Id
  @SequenceGenerator(name = "revisionSeq", sequenceName = "REVISION_DATOS_ID_SEQ", allocationSize = 1, initialValue = 1)
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "revisionSeq")
  private int id;

  @RevisionTimestamp
  private Date modifiedAt;
  private String username;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  @Temporal(value = TemporalType.TIMESTAMP)
  public Date getModifiedAt() {
    return modifiedAt;
  }

  public void setModifiedAt(Date modifiedAt) {
    this.modifiedAt = modifiedAt;
  }

}

您还必须定义一个修订侦听器来处理数据在您的自定义修订实体中的初始化方式。您的侦听器必须实现 RevisionListener。

public class AuditingRevisionListener implements RevisionListener {
  private static Log log = LogFactory.getLog(AuditingRevisionListener.class.getName());

  @Override
  public void newRevision(Object revisionEntity) {
    AuditedRevisionEntity revEntity = (AuditedRevisionEntity) revisionEntity;
    String userName = null;
    try {
      if (SecurityContextHolder.getContext().getAuthentication() != null) {
        Object principal = getCurrentUserInfo();
        if (principal == null) {
          userName = "system";
        } else if (principal instanceof User) {
          userName = ((User) principal).getUsername();
        } 
      }
    } catch (Exception e) {
      log.error("Error auditing username.", e);
    }
    revEntity.setUsername(userName);
    revEntity.setModifiedAt(new Date());
  }
}

请记住,这些类必须可以通过休眠访问,请检查:Why Hibernate Envers is ignoring my custom RevisionEntity?

【讨论】:

  • 感谢@Ricardo,这很有帮助。但是我不明白为什么我需要这样做,因为根据 Envers 文档,修订时间戳应该是开箱即用的。
【解决方案2】:

有一个由名为 REVINFO 的环境自动创建的表,其中包含时间戳。

它包含 REV 作为“_AUD”表中您的修订号的键。 这个数字在所有“_AUD”表中是唯一的。

参见段落:15.8。了解 Envers Schema https://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch15.html

【讨论】:

    【解决方案3】:

    这对我有用:

    select
    
        to_char(
    
                    TO_DATE('01/01/1970 00:00:00','DD/MM/YYYY HH24:MI:SS')
    
                    + (rev.timestamp /1000/60/60/24 ||' day')::interval, 'YYYY/MM/DD'
    
            )
    
    from audit_table_aud aud
    
    join revisions as rev on aud.rev = rev.id
    

    【讨论】:

      猜你喜欢
      • 2020-03-11
      • 1970-01-01
      • 2021-12-11
      • 2012-12-17
      • 2017-09-14
      • 2013-05-24
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      相关资源
      最近更新 更多