Hibernate Envers:暂时禁用审计

问题描述

我在一个启用了 envers 的项目中创建了一个实体复制器,但对于这个复制器,我不需要审计:有没有办法暂时禁用 envers 审计?

我知道有侦听器可以作为拦截器(在审计触发器之前),但我还需要知道从哪里触发审计(例如调用触发审计的服务的控制器)。

我不知道这是否可能。

谢谢

解决方法

Envers 注册了一组由 Hibernates Event system 触发的事件监听器。

为了实现条件审计(see envers documentation),您需要将这些侦听器替换为您自己的实现。以下 event types 会触发 enver 的侦听器:

  • EventType.POST_INSERT
  • EventType.PRE_UPDATE
  • EventType.POST_UPDATE
  • EventType.POST_DELETE
  • EventType.POST_COLLECTION_RECREATE
  • EventType.PRE_COLLECTION_REMOVE
  • EventType.PRE_COLLECTION_UPDATE

由于您只想跳过对复制实体的审核,因此您只需替换 org.hibernate.envers.event.spi.EnversPostInsertEventListenerImpl

在您的实体中,您添加一个临时字段作为标志。通过这种方式,您可以在侦听器实现中确定实体是否被复制。

public class YourEntity {

    @Transient
    private boolean copy;

    public boolean isCopy() {
        return copy;
    }

    public void setCopy(boolean copy) {
        this.copy = copy;
    }
}

然后你通过扩展默认监听器来实现你的监听器:

public class CustomPostInsertListener extends EnversPostInsertEventListenerImpl {

    public CustomPostInsertListener(EnversService enversService) {
        super(enversService);
    }

    @Override public void onPostInsert(PostInsertEvent event) {
        if (event.getEntity() instanceof YourEntity
                && ((YourEntity) event.getEntity()).isCopy()) {
            // Ignore this entity
            return;
        }
        super.onPostInsert(event);
    }
}

在您的复印机中,您需要为实体设置 copy 标志。

public YourEntity copyEntity(YourEntity entityToCopy){
    YourEntity newEntity;
    //... your copy logic

    newEntity.setCopy(true);
    return newEntity;
}

然后您需要创建自己的 org.hibernate.integrator.spi.Integrator 实现。最简单的方法是扩展 org.hibernate.envers.event.spi.EnversIntegrator:

package com.your.project.audit;

public class EnversCustomIntegrator extends EnversIntegrator {

    public static final String  AUTO_REGISTER   = "hibernate.listeners.envers.autoRegister";
    private AuditConfiguration  enversConfiguration;

    @Override
    public void integrate(org.hibernate.cfg.Configuration configuration,SessionFactoryImplementor sessionFactory,SessionFactoryServiceRegistry serviceRegistry) {



        final EventListenerRegistry listenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);
        listenerRegistry.addDuplicationStrategy(EnversListenerDuplicationStrategy.INSTANCE);

        enversConfiguration = AuditConfiguration.getFor(configuration,serviceRegistry.getService(ClassLoaderService.class));

        if (enversConfiguration.getEntCfg().hasAuditedEntities()) {
            listenerRegistry.appendListeners(EventType.POST_DELETE,new EnversPostDeleteEventListenerImpl(enversConfiguration));
            listenerRegistry.appendListeners(EventType.POST_INSERT,new CustomPostInsertListener(enversConfiguration));
            listenerRegistry.appendListeners(EventType.POST_UPDATE,new EnversPostUpdateEventListenerImpl(enversConfiguration));
            listenerRegistry.appendListeners(EventType.POST_COLLECTION_RECREATE,new EnversPostCollectionRecreateEventListenerImpl(enversConfiguration));
            listenerRegistry.appendListeners(EventType.PRE_COLLECTION_REMOVE,new EnversPreCollectionRemoveEventListenerImpl(enversConfiguration));
            listenerRegistry.appendListeners(EventType.PRE_COLLECTION_UPDATE,new EnversPreCollectionUpdateEventListenerImpl(enversConfiguration));
        }

    }
}

最后,您需要在 META-INF/services/org.hibernate.integrator.spi.Integrator 文件中添加您的 Integrator 实现。

com.your.project.audit.EnversCustomIntegrator