我们有一个带有String属性的实体,该实体经常更改,因此我们在其上使用了@NotAudited
。但这会导致审计表中的列为空(这是可以理解的)。
如果实体(其中之一是已审计的列)发生更改,我们想将String属性的实际值插入审计表,但是如果所述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 );
}
}
}
此撰写本文时所需的方法还要求您也覆盖
EnversIntegrator
中的侦听器注册。扩展这些侦听器需要状态比较的实用知识,而不是提供可插入的解决方案,这给用户带来了沉重的负担。可插拔解决方案是HHH-11326的目标。我要介绍的是一个类似于JPA的概念,其中
@AuditListener
可以放置在已审计的实体类上,而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,该API使用户可以轻松决定是否否决审核操作,而不必了解很多Hibernate事件如何或Envers的内部原理。正如JIRA指出的那样,我计划在接下来的几个月中在Hibernate Envers 6.0的下一个主要版本中引入这个新的
@AuditListener
概念。关于java - 启用-插入@NotAudited字段的实际值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41736527/