-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Matt Benson opened SPR-2847 and commented
Current Hibernate wisdom says to close and recreate the Session on any HibernateException. When using Spring + Hibernate it is possible, having delved into Spring's inner workings, to gracefully recover from e.g. StaleObjectStateExceptions (or HibernateOptimisticLockingFailureExceptions, as it were) and install a new Session, binding into the TransactionManager. The OpenSessionInViewInterceptors are completely compatible with this approach, but the filter implementations fall down. This is because while the Interceptors implement the session management in separate methods, the Filters accomplish everything in a single method, storing the Session in a local variable. If the current Session has changed, the following happens:
Session.close() throws an Exception due to its already having been closed.
SessionFactoryUtils logs, but does not propagate, the Exception.
The active Session is not closed, thus its Connection is never released.
The simple fix is to use:
session = ((SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory)).getSession();
instead of
TransactionSynchronizationManager.unbindResource(sessionFactory);
in the finally clause surrounding the doFilter() call.
Since my use case can be considered advanced Hibernate usage, I have classified this issue as an Improvement. However, since the Interceptors--whether by design or by luck--do not suffer from this shortcoming, I have left the priority at Major.
br,
Matt
Affects: 2.0 final