26 6 / 2009
Auditing using Interceptors in Hibernate
This would probably work only in Hibernate 3. Its loosely based on https://www.hibernate.org/48.html. I am showing a very basic example which sets the created time in a property when an entity is inserted and the updated time in another property when its updated.
Hibernate allows interceptors to be registered and calls it when an entity’s state changes during its lifecycle. Refer the Interceptor documentation for information on its methods. The method names give you an idea of when it gets called.
In order for the Interceptor to identify the entities to be audited, the entities implement an interface. Like this
AuditStamp contains the audit information that is set or updated by the interceptor. It can range from simple datetime to user information. The AuditStamp class shown below just has dates, but more can be added as needed. The advantage of having it as a separate class is that when more audit information needs to be added, the entity implementing Auditable remains unaffected.
This AuditStamp class is mapped in Hibernate using a custom type
Refer the CompositeUserType documentation to see how this type is implemented. Now the Interceptor is also a minimal implementation, it can be enriched as needed.
Interceptors are little if you need to change the state of an entity. Even though the first parameter in onSave and onFlushDirty is the entity itself, changing the state of it does not seem to work. Instead the third parameter contains the values of all the properties in the entity in the same order as property names are specified in the fourth parameter.
The setValue does the magic of finding the index of the property and setting the value.
Interceptors come in two flavors: Session-scoped and SessionFactory-scoped.
A Session-scoped interceptor is specified when a session is opened using one of the overloaded SessionFactory.openSession() methods accepting an Interceptor.
Session session = sf.openSession( new AuditInterceptor() );
A SessionFactory-scoped interceptor is registered with the Configuration object prior to building the SessionFactory. In this case, the supplied interceptor will be applied to all sessions opened from that SessionFactory; this is true unless a session is opened explicitly specifying the interceptor to use. SessionFactory-scoped interceptors must be thread safe, taking care to not store session-specific state since multiple sessions will use this interceptor (potentially) concurrently.
new Configuration().setInterceptor( new AuditInterceptor() );
That’s it.
The AuditStamp is specified in the hibernate mapping as a custom type. A typedef can be used as well.
Permalink 14 notes