views:

129

answers:

3

Hi all,

I want to write a history component that tracks changes to a particular object type and writes history rows based on the difference. Note this is not a general audit system it is specific for one object type.

I figure I can hook into the hibernate event model and listen for events that tells me when things have changed, watch for any changes to instances of the object type I am interested in, and then have some custom code generate the history rows.

I want the history rows written in the same transaction, and ideally using hibernate (therefore using the same Session)

I have some questions/concerns

  • Which hibernate events should I hook, assuming I want to trap just changes?
  • How do I go about participate in the same Session/transaction as the Session that are generating the events. I have read there are issues interacting with the Session inside event handlers?

Any help appreciated.

+2  A: 

There is a generic audit solution for hibernate entities, called envers, that should do the trick.

However, if this solution is not enough (as your comment suggests), the org.hibernate.events package defines the usable events. In you case, I would suggest to implement at least the PostUpdateEventListener interface.

Riduidel
Thanks but I don't see a way of having a new instance of a "custom" entity created per each change of a target entity. It looks like a good general audit system but I need something more specific.
Mike Q
Thanks, PostUpdate event was indeed the way to go. I good some good ideas from the envers source on how to interact with the Session/Transaction.
Mike Q
+1  A: 

The pre-insert and pre-update events seem a good choice.

Your PrePersistEvent and PreUpdateEvent have a getSession() method which is:

the session event source for this event. This is the underlying session from which this event was generated.

So, using it, you can create new objects and persist them within the same session and transaction.

Bozho
A: 

When using the these events make sure that you do not touch the session that caused the events to fire. Get the session and retrieve the session factory and open a new session. This will still be in the same transaction, but you will avoid a lot of Hibernate problems.

Also, if you start traversing object graphs on the object that caused the event to fire, then you can get strange errors as you have changed collection states during a flush. There are Jira tickets open for this "bug".

Kango_V