问题
I have a requirement where I want to audit records only on change of Status field. I've followed documentation chapter tutorial "15.8. Conditional auditing".
Step 1: Turn off automatic Envers event listeners registration. I have following:
<prop key="hibernate.listeners.envers.autoRegister">false</prop>
Step 2: Create subclasses for appropriate event listeners.
public class DeleteEnversListener extends EnversPostDeleteEventListenerImpl {
private static final long serialVersionUID = 5906427978349712224L;
private static Log log = LogFactory.getLog(DeleteEnversListener.class);
public DeleteEnversListener(AuditConfiguration enversConfiguration) {
super(enversConfiguration);
}
@Override
public void onPostDelete(PostDeleteEvent event) {
log.info("!!! just logging entity !! "+ event.getEntity());
super.onPostDelete(event);
}
}
In similar way, I have
- InsertEnversListener
- UpdateEnversListener
- DeleteEnversListener
- CollectionRecreateEnversListener
- PreCollectionRemoveEnversListener
- PreCollectionUpdateEnversListener
Step 3: Create your own implementation of org.hibernate.integrator.spi.Integrator
public class CustomEnversIntegrator extends EnversIntegrator {
private static Log log = LogFactory.getLog(CustomEnversIntegrator.class);
@Override
public void integrate(Configuration configuration,
SessionFactoryImplementor sessionFactory,
SessionFactoryServiceRegistry serviceRegistry) {
super.integrate(configuration, sessionFactory, serviceRegistry);
final AuditConfiguration enversConfiguration = AuditConfiguration.getFor( configuration, serviceRegistry.getService( ClassLoaderService.class ) );
EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
System.out.println("Registering event listeners");
if (enversConfiguration.getEntCfg().hasAuditedEntities()) {
listenerRegistry.appendListeners(EventType.POST_INSERT, new InsertEnversListener(enversConfiguration));
listenerRegistry.appendListeners(EventType.POST_UPDATE, new UpdateEnversListener(enversConfiguration));
listenerRegistry.appendListeners(EventType.POST_DELETE, new DeleteEnversListener(enversConfiguration ) );
listenerRegistry.appendListeners(EventType.POST_COLLECTION_RECREATE, new CollectionRecreateEnversListener(enversConfiguration ) );
listenerRegistry.appendListeners(EventType.PRE_COLLECTION_REMOVE, new PreCollectionRemoveEnversListener(enversConfiguration ) );
listenerRegistry.appendListeners(EventType.PRE_COLLECTION_UPDATE, new PreCollectionUpdateEnversListener(enversConfiguration ) );
}
}
}
Step 4: For the integrator to be automatically used when Hibernate starts up, you will need to add a META-INF/services/org.hibernate.integrator.spi.Integrator
file. Here is content of org.hibernate.integrator.spi.Integrator
file
com.hib.sample.listener.CustomEnversIntegrator
I am not sure, if I am missing anything. I am using JBOSS AS 7.0 with Hibernate 4.1.8
回答1:
Here is a Spring-only solution for the conditional Envers
auditing without an ugly META-INF
folder etc. All what you need is a bean in your configuration class and a CustomEnversEventListener
.
@Bean
public EventListenerRegistry listenerRegistry(EntityManagerFactory entityManagerFactory) {
ServiceRegistryImplementor serviceRegistry = entityManagerFactory.unwrap(SessionFactoryImpl.class).getServiceRegistry();
final EnversService enversService = serviceRegistry.getService(EnversService.class);
EventListenerRegistry listenerRegistry = serviceRegistry.getService(EventListenerRegistry.class);
listenerRegistry.setListeners(EventType.POST_UPDATE, new CustomEnversEventListener(enversService));
return listenerRegistry;
}
and
public class CustomEnversEventListener extends EnversPostUpdateEventListenerImpl {
CustomEnversEventListener(EnversService enversService) {
super(enversService);
}
@Override
public void onPostUpdate(PostUpdateEvent event) {
// custom conditional stuff
super.onPostUpdate(event);
}
}
If you want to customise only one listener i.e. EnversPostUpdateEventListener, you don't need to disable hibernate.listeners.envers.autoRegister
in order to let Envers register the other listener.
Then you can override Envers
listeners by listenerRegistry.setListeners
or append by listenerRegistry.appendListeners
回答2:
Try to place integrator file into:
sample.war\WEB-INF\classes\META-INF\services\...
回答3:
Maybe...
In my case, I use Maven, and I had to include in the pom.xml
, the following line : <include>**/*.Integrator</include>
, because the file was not packaged in the .ear
.
My pom.xml
:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
<include>**/*.Integrator</include>
</includes>
</resource>
...
回答4:
creating a file org.hibernate.integrator.spi.Integrator (containing the qualified name of my custom integrator) in a folder META-INF/services/ under src/main/resources of my maven project made my custom integrator code be called.
回答5:
@ComponentScan(basePackages = {"com.example.demo"}, lazyInit = true)
Adding lazyInit = true, triggered the custom integrator for me.
来源:https://stackoverflow.com/questions/14250612/conditional-envers-auditing