lunedì 2 febbraio 2009

Remember: close your Hibernate Session after a rollback

Yet another time Hibernate stroke me down, and I keep forgetting about this so I write it down forever: always close your Hibernate Session after a rollback happens.
This time I had an hard time trying to understand what was going on.
I'm trying Google Guice and warp-persist with wicket, so I wrote a simple one page application to test transaction management.
One transactional method threw an exception, I caught it in the upper application layer and tried to manage the error: my test did nothing other than write a log line.
I had my transaction rolled back, but my entity object was anyway written in the database. What took me away from the right direction was that an (almost) identical application instead worked (no record written in the db).
Eventually a managed to understand: I tried a session.flush() just before throwing my exception and everything was rolled back.
My fault was to think my session was sort of rolled back too, or at least empty.
Instead it was in Flushmode.AUTO, and the roll back happened BEFORE anything was written by my session to the db.
My entity object continued to be bound to that session.
After I caught the exception and logged one line, control went back to the application and a flush was eventually done by warp-persist open-session-in-view-filter, writing the record in the db.
My other almost identical application worked just because it did a different query inside that transaction, and Hibernate decided (do you remember Flushmode.AUTO ?) it was better to flush my session before executing that query, and so it applied rollback accordingly.
I think it's better to set flushmode.COMMIT: it's more natural to think that way, in my opinion. Anyway, if you catch exception from a transaction, close your session and get a new one.