Attaching revision details entity to REVINFO
appletree Nov 3, 2010 9:08 AMIn our current envers-like system, we have an entity called ChangeOrigin that we associate with every revision. Similar to REVINFO except ChangeOrigin can span multiple transactions. It basically contains an Author entity, IP address, time change was requested, how the change was made (api, web, flash widget, other methods), etc.
So we have a custom Revision entity with an AuditListener. In the AuditListener, we simply set the changeOrigin entity on the revisionEntity from a ThreadLocal object:
revisionEntity.setChangeOrigin(revisionData.getChangeOrigin());
Now the problem is we get very strange behavior when the Author is updating himself... Basically, there's a changeOrigin.getAuthor() that returns a Person entity. Sometimes the author wants to update his Person. So we used to load the author in a different transaction, so the changeOrigin.getAuthor() would be a detached Person. That wasn't a problem. Now it is. So we tried setting changeOrigin.setAuthor(new DummyPerson(sameIdOfAuthor)). That has the same odd behavior. changeOrigin.setAuthor(null) works perfectly fine except, of course, we have no author info! So there are 2 options as we see them:
- Retrieve author in the web tier, set in the ThreadLocal for the ChangeOrigin and whenever saving any entity in the manager/transaction tier, look at the ThreadLocal for the ChangeOrigin and make sure if getAuthor() is being updated, then call changeOrigin.setAuthor(currentPersistentPerson).
- Subclass an AuditStrategy and override some methods to get access to hibernate directly and do our checks there.
I really don't like the first option as we have to remember to do that properly every time or experience weird, and sometimes difficult to detect, hibernate session behavior. Plus it makes our code ugly as we now have to deal with ChangeOrigins instead of having them automatically handled in the web tier. The 2nd option, is this advisable?
This must be a pretty common scenario, wanting to link an Author entity to the revision, right? And you can't load Author twice with hibernate in case you are also making changes to the Author entity, BY the author....