Look at the org.hibernate.Interceptor interface - there are callbacks in 3.x for afterTransactionBegin, beforeTransactionCompletion, afterTransactionCompletion that will be called.
Some thoughts on your specific points issues:
1. Audit_id generation only when an "auditable" table comes into play
First, I would think about Entities not "tables" - so, when some entity that requires auditing is manipulated, you want to store data. So now either use a marker interface or annotation (I'm using annotations for an app I'm building right now and they work well for me -- especially because you can parameterize them at build-time.)
Next, you want to use a Session scoped Interceptor (vs. a SessionFactory scoped interceptor) - this lets you store state information in the interceptor. Create a master "Audit" record with a OneToMany relationship to "AuditDetails". Fill ou the Audit record with your user, datetime, etc... and keep that in an instance field of the interceptor. Then as new auditable entities come into play, add the details of those entities as AuditDetail objects to the main Audit record. That will give you your "audit_id" that spans multiple tables.
2. History for some objects - see the documentation on the Hibernate Wiki on how to do this. Just adapt the same strategy from #1 to add some History. You could possibly make a relationship to your Audit object so you have a reference to the Audit_id.
3. Dealing with transaction rollbacks - I haven't tried using the new transaction-aware methods on the Interceptor interface. Perhaps someone who has can comment on how these work with rolled-back transactions?
My guess is that everything rolls back. One way I've solved this problem before (in a non-hibernate world) was to use a thread-pool and push the audit information into the pool for persistence. The new JDK1.5 concurrency library is terrific for this kind of stuff. Most (if not all?) Java TX managers manage transactions on a per-thread basis, so if you start a new thread you can get into a new transactions. Its a heavier way to do things, even when using a thread pool, and not very "J2EE-like", but perhaps you could use this pattern when dealing with rolled back transactions only - normally executing TXNs could use the shared connection method described in the wiki.
Caveat - all of this stuff is Hibernate-specific, so its not plain-vanilla "EJB3" so it won't transfer to other EJB3 implementations - but of course, you are posting on the hibernate forum ;-)
good luck!
Erik
|