views:

50

answers:

2

Hi,

We have a requirement on our project, where we need to maintain a sort of history of changes that are made to certain Entities in the Application. The the Application is a Java Web App based on Struts, Spring and Hibernate. What sort of approaches have been used in this case ?

  • Triggers on the respective tables is one idea but they are not easily maintainable ? and perhaps also they should not be part of transactions (its ok if the triggers fail, but the entity update transactions should not fail ).
  • Use AoP for this since its a cross-cutting concern, but has to be really granular, as in capturing only the values when the entity changes. (All edits don't have their corresponding different methods... many edits happen in a single java Method).
  • Use Hibernate Event Listeners.

Are there any other approaches for doing this sort of activity ?

+2  A: 

Because you said

All edits do not have their corresponding different methods... many edits happen in a single java Method

Even if your method just receive one argument as parameter and you can retrieve its relationships, AOP still can be a nice idea. I strongly advice you to see this nice article

The Hibernate documentation itself says:

Hibernate Interceptor allows the application to inspect and/or manipulate properties of a persistent object before it is saved, updated, deleted or loaded. One possible use for this is to track auditing information.

But it also says

Ensure that you do not store sessionspecific states, since multiple sessions will use this interceptor potentially concurrently

If you use a Spring managed Transaction, you can get the session atached to the current Thread by using sessionFactory.getCurrentSession();

public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
    if(entity instanceof SomeEntity) {
        Session session = sessionFactory.getCurrentSession();

See getCurrentSession() documentation

If not, you should create a local Hibernate interceptor (attached to the opened Session) instead of a global interceptor(attached to the SessionFactory), and then, set up its session

AuditableInterceptor interceptor = new AuditableInterceptor()
Session session = sessionFactory.openSession(interceptor);

/**
  * do it before processing anything if you use local interceptor
  */ 
interceptor.setSession(session);

About Triggers, it depends on other issues like DB administration (you have DB administration access. If not, Talk to DBA is your best bet).

Arthur Ronald F D Garcia
Thanks for the info Arthur. For the simple implementation I am trying to extend Hibernate Event Listener.
Icarus
+1, for the general-purpose explanation.
Bozho
+1 as Bozho said
Pascal Thivent
+2  A: 

JBoss Envers supports audition and versioning - take a look.

Bozho
@Bozho Interesting (+1) Do you use it successfully ??
Arthur Ronald F D Garcia
@Arhtur - no, alas. But I know people that use it and say it's good :)
Bozho
And +1 too. Envers seems to fit well here.
Pascal Thivent