Hibernate Envers是审计实体的框架。顾名思义,Hibernate Envers是在Hibernate之上开发的,它将在Hibernate上实现JPA。Hibernate Envers 为实体类提供了简单的审核、版本控制解决方案。
Hibernate Envers的优点:
- 审核 JPA 规范定义的所有映射。
- 审核 Hibernate 特定映射,扩展 JPA 规范。
- 使用修订实体记录每个修订的数据。
- 查询实体及其关联的审核数据。
- 独立于数据库的审计。
- 查询类似于实体的实体修订。
在应用程序中实现休眠环境
在生成工具配置文件中添加休眠依赖项。
使用@Audited注释注释实体或实体属性,请确保实体主键是不可变类。
修订
Hibernate Envers使用与源代码版本控制工具相同的概念,称为修订版。修订标识在事务边界内发生的所有审核属性的实体及其关联的更改集合。这些修订是全局的和数字的。
Hibernate Envers中使用的一些重要注释
- @Audited:我们可以将此注释应用于字段或类,当应用于类时,指示应审核其所有属性,当应用于字段时,指示应审核此字段。
- @NotAudited:应用于字段时,指示不应审核此字段。
- @AuditingOverride:注释用于覆盖从超类类型继承的超类或单个属性的审核行为,或嵌入组件中的属性。
- @AuditingOverrides:注释用于覆盖嵌入组件中一个或多个字段(或属性)的审核行为。
- @AuditTable:默认情况下,Hibernate在被审计实体的表名中添加“_AUD”后缀。我们可以使用@AuditTable注释或通过在配置中配置不同的前缀或后缀来定义不同的表名。
- @RevisionNumber:标记一个属性,该属性将在修订实体中保存修订的编号,此属性的值应形成严格递增的数字序列。此属性的值不会由 Envers 设置。在大多数情况下,这应该是自动生成的数据库分配的主 ID。
- @RevisionTimestamp:标记一个属性,该属性将在修订实体中保存修订的时间戳,此属性的值将由 Envers 自动设置。
- @AuditJoinTable:此注释用于审核实体关系,默认情况下,审核联接的名称将串联为拥有关联的实体的主表的名称和关联引用的实体的主表的名称。
- 如果我们在实体中使用辅助表,那么将以相同的方式生成它们的审计表(通过添加前缀和后缀)。如果要覆盖此行为,可以使用@SecondaryAuditTable和@SecondaryAuditTables批注。
- 我们可以覆盖从@MappedSuperclass或嵌入式组件中继承的某些字段/属性的审核行为,您可以在组件的子类型或使用站点上应用@AuditOverride注释。
- 如果父实体被@Audited注释并且关联实体没有被审计,那么它将尝试获取最新的关联,如果没有找到,那么它将抛出异常,在这种情况下,我们可以@NotFound注释来忽略异常。
Envers 的休眠配置属性
- hibernate.envers.audit_table_prefix :将附加到审核实体名称前面以创建实体名称的字符串,并将保存审核信息。
- hibernate.envers.audit_table_suffix(默认值:_AUD):将追加到审核实体的名称以创建实体名称并保存审核信息的字符串。我们可以对实体使用@AuditTable注释进行覆盖。
- hibernate.envers.revision_field_name(默认值:REV):审核实体中将保存修订号的字段的名称。
- hibernate.envers.revision_type_field_name(默认值:REVTYPE):审核实体中将保存修订类型的字段的名称。
Hibernate Envers 的用法
- 我们需要实现 RevisionListener 来创建新的修订实体,通过实现 newRevision(对象修订实体)
- 通过扩展 DefaultRevisionEntity 或创建包含 setter/getter 方法的简单普通 java 对象来创建修订实体类,如果我们扩展 DefaultRevisionEntity,则将添加两个用 @RevisionNumber 和 @RevisionTimestamp 注释的属性。用@RevisionEntity批注此类,以便将其用于创建修订。如果多个注释标有@RevisionEntity注释,那么它将抛出错误。
读取被审计实体
AuditReader 是读取实体修订的类,它具有多种方法来读取实体 ID 的实体修订。它还允许访问与实体类型关联或受日期范围限制的修订列表。该 API 还提供了一种获取修订元数据的方法,以便我们可以知道何时发生更改,以及我们可能根据实现需求存储在修订实体上的任何其他自定义属性。
Eaxmple:
AuditReader reader = AuditReaderFactory.get( entityManager ); Event firstRevision = reader.find( Event.class, 2L, 1 );
有条件审计
Hibernate Envers添加了一系列Hibernate会话侦听器,它将被自动注册。
- 为了创建条件审计,我们需要通过将此属性设置为 false 来关闭事件侦听器的自动注册,hibernate.envers.autoRegisterListeners。
- Hibernate envers 为插入、更新和删除等不同操作提供了事件侦听器,假设如果我们想为插入添加条件审计,然后创建一个扩展 EnversPostInsertEventListenerImpl 类的类,在其中添加自定义逻辑。
- 创建集成器的自定义实现或扩展 EnversIntegrator 类,并使用以前创建的事件侦听器而不是默认事件侦听器。
- Hibernate Envers将使用META-INF/services/org.hibernate.integrator.spi.Integrator文件来加载Integrator类,创建一个上面的文件并编写实现接口的类的完全限定名称,以便加载它而不是默认的。
跟踪修订期间修改的实体名称
默认情况下,不会跟踪在每个修订中已更改的实体类型。这意味着必须查询存储审核数据的所有表,以便检索在指定修订期间所做的更改。Envers 提供了一种简单的机制,用于创建 REVCHANGES 表,该表存储已修改的持久对象的实体名称。单个记录封装修订标识符(REVINFO 表的外键)和字符串值。
我们可以通过多种方式实现这一点:
- org.hibernate.envers.track_entities_changed_in_revision参数设置为 true。在这种情况下,org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity将被隐式用作修订日志实体。
- 创建一个自定义修订实体,用于扩展 org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity 类。
- 使用 @org.hibernate.envers.ModifiedEntityNames 注释标记自定义修订实体的相应字段。该属性必须是 Set<String> 类型。
结论
Hibernate Envers 是以更简单的方式提供审计的框架,我们还可以自定义 Hibernate 默认行为,轻松读取实体修订,而且它是数据库不可依赖的。