Envers - 插入@NotAudited 字段的实际值
Envers - insert actual value of @NotAudited field
我们有一个带有字符串 属性 的实体,该实体经常更改,因此我们在其上使用了 @NotAudited
。但这会导致该列在审计中为空table(可以理解)。
我们想将字符串 属性 的实际值插入审计 table,如果实体(其中一个审计列)发生变化,但不想插入新的记录到审计table,如果说String属性改变。
我该怎么做?
您描述的就是我们所说的条件审计,您可以在 Envers 文档中找到详细信息。
基本原则是,您将继续用 @Audited
注释 属性,但要确定是否有任何其他 属性 在 PostUpdateEvent
期间最有可能更改,如果您的特定 属性 已全部更改,您不会将 PostUpdateEvent
委托给 Envers 默认侦听器实现。
一些伪代码可能看起来像这样:
public class CustomEnversPostUpdateEventListener
extends EnversPostUpdateEventListenerImpl {
public CustomEnversPostUpdateEventListener(EnversService enversService) {
super( enversService );
}
@Override
public void onPostUpdate(PostUpdateEvent event) {
final String entityName = event.getPersister().getEntityName();
if ( getEnversService().getEntityConfigurations().isVersioned( entityName ) ) {
if ( MySpecialEntity.class.getName().equals( entityName ) ) {
// Compare event.getState() against event.getOldState()
// Determine if only your special String changed or not
if ( !otherFieldsChangedBesidesSpecialProperty ) {
return;
}
}
// delegate to default implementation
super.onPostUpdate( event );
}
}
}
此时 write-up 所需的方法要求您也覆盖 EnversIntegrator
中的侦听器注册。扩展这些侦听器需要状态比较的工作知识,而不是提供可插入的解决方案,这会给用户带来很大的负担。
可插拔解决方案是 HHH-11326 的目标。我想介绍的是一个 JPA-like 概念,其中 @AuditListener
可以放在被审计的实体 class 上,而 Envers 将为此行为委托给侦听器实现。
关于这将如何工作还没有任何确定的事情,所以下面只是我个人对此事的想法以及它可能看起来如何并在代码方面发挥作用的头脑转储:
public class MyEntityAuditListener extends AbstractAuditListener {
@Override
public boolean onPostUpdate(EnversPostUpdateEvent event) {
// return true = allow the audit operation
// return false = veto the audit operation
if ( event.getPropertyChangeCount() != 1 ) {
return true;
}
return !event.isPropertyChanged( "mySpecialString" );
}
}
@Entity
@Audited
@AuditListener(MyEntityAuditListener.class)
public class MyEntity {
// ...
private string mySpecialString;
}
好的部分是 EnversPostUpdateEvent
允许我们抽象出很多 Envers 的内部结构,公开一个干净的 API 让用户可以轻松决定是否否决一个审计操作而无需了解 Hibernate 事件或 Envers 的内部工作原理。
正如 JIRA 所指出的,这个新的 @AuditListener
概念是我计划在未来几个月内在 Hibernate Envers 6.0 的下一个主要版本中引入的。
我们有一个带有字符串 属性 的实体,该实体经常更改,因此我们在其上使用了 @NotAudited
。但这会导致该列在审计中为空table(可以理解)。
我们想将字符串 属性 的实际值插入审计 table,如果实体(其中一个审计列)发生变化,但不想插入新的记录到审计table,如果说String属性改变。
我该怎么做?
您描述的就是我们所说的条件审计,您可以在 Envers 文档中找到详细信息。
基本原则是,您将继续用 @Audited
注释 属性,但要确定是否有任何其他 属性 在 PostUpdateEvent
期间最有可能更改,如果您的特定 属性 已全部更改,您不会将 PostUpdateEvent
委托给 Envers 默认侦听器实现。
一些伪代码可能看起来像这样:
public class CustomEnversPostUpdateEventListener
extends EnversPostUpdateEventListenerImpl {
public CustomEnversPostUpdateEventListener(EnversService enversService) {
super( enversService );
}
@Override
public void onPostUpdate(PostUpdateEvent event) {
final String entityName = event.getPersister().getEntityName();
if ( getEnversService().getEntityConfigurations().isVersioned( entityName ) ) {
if ( MySpecialEntity.class.getName().equals( entityName ) ) {
// Compare event.getState() against event.getOldState()
// Determine if only your special String changed or not
if ( !otherFieldsChangedBesidesSpecialProperty ) {
return;
}
}
// delegate to default implementation
super.onPostUpdate( event );
}
}
}
此时 write-up 所需的方法要求您也覆盖 EnversIntegrator
中的侦听器注册。扩展这些侦听器需要状态比较的工作知识,而不是提供可插入的解决方案,这会给用户带来很大的负担。
可插拔解决方案是 HHH-11326 的目标。我想介绍的是一个 JPA-like 概念,其中 @AuditListener
可以放在被审计的实体 class 上,而 Envers 将为此行为委托给侦听器实现。
关于这将如何工作还没有任何确定的事情,所以下面只是我个人对此事的想法以及它可能看起来如何并在代码方面发挥作用的头脑转储:
public class MyEntityAuditListener extends AbstractAuditListener {
@Override
public boolean onPostUpdate(EnversPostUpdateEvent event) {
// return true = allow the audit operation
// return false = veto the audit operation
if ( event.getPropertyChangeCount() != 1 ) {
return true;
}
return !event.isPropertyChanged( "mySpecialString" );
}
}
@Entity
@Audited
@AuditListener(MyEntityAuditListener.class)
public class MyEntity {
// ...
private string mySpecialString;
}
好的部分是 EnversPostUpdateEvent
允许我们抽象出很多 Envers 的内部结构,公开一个干净的 API 让用户可以轻松决定是否否决一个审计操作而无需了解 Hibernate 事件或 Envers 的内部工作原理。
正如 JIRA 所指出的,这个新的 @AuditListener
概念是我计划在未来几个月内在 Hibernate Envers 6.0 的下一个主要版本中引入的。