Hibernate does a neat trick where it tracks objects that have been changes since being loaded from the database. Once Hibernate provides an object, make a modification and flush the Session – Hibernate knows the object was changed and will propagate to the database accordingly.
I was trying to construct a more explicit system, where objects had to be explicitly marked for saving. Conveniently for my codebase, all the objects that come out of Hibernate go through a couple entry points that abstract Hibernate from the rest of the system. Using Session.evict() to dissociate the object from Hibernate’s tracking, then subsequently using Session.save() or Session.update() to reassociate, seemed workable.
Naturally, there’s a fly in this soup. Hibernate (v3) doesn’t like this pattern. It reports an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session). From what I can see, I’m not the only one who’s seen this issue. I don’t remember where I got the hint from, but it turns out that if I call Session.flush() after the Session.evict(), most of the problems go away.
In the end, I tossed the idea out as a bad one: overthinking and not using the framework enough. Hibernate supports optimistic concurrency collision detection via versioning/timestamps. Since the purpose of this exercise was to limit the damage that accidental and parallel writes could do, Hibernate’s support was sufficient.