Опираясь на ответ Божо и принимая во внимание комментарии к нему, следующее, по-видимому, является полным (совместимым с Hibernate 4) решением, решающим проблему сброса соединения. Насколько я могу сказать, весенний уровень будет гарантировать вызов метода cleanupTransaction, но если это на самом деле не гарантировано, это может потребовать переосмысления из-за потенциальной утечки памяти permGen и побочных эффектов после запроса на объекте соединения. .
public class HibernateExtendedJpaDialect extends HibernateJpaDialect {
ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<>();
ThreadLocal<Integer> originalIsolation = new ThreadLocal<>();
@Override
public Object beginTransaction(EntityManager entityManager,
TransactionDefinition definition)
throws PersistenceException, SQLException, TransactionException {
boolean readOnly = definition.isReadOnly();
Connection connection =
this.getJdbcConnection(entityManager, readOnly).getConnection();
connectionThreadLocal.set(connection);
originalIsolation.set(DataSourceUtils
.prepareConnectionForTransaction(connection, definition));
entityManager.getTransaction().begin();
return prepareTransaction(entityManager, readOnly, definition.getName());
}
/*
We just have to trust that spring won't forget to call us. If they forget,
we get a thread-local/classloader memory leak and messed up isolation
levels. The finally blocks on line 805 and 876 of
AbstractPlatformTransactionManager (Spring 3.2.3) seem to ensure this,
though there is a bit of logic between there and the actual call to this
method.
*/
@Override
public void cleanupTransaction(Object transactionData) {
try {
super.cleanupTransaction(transactionData);
DataSourceUtils.resetConnectionAfterTransaction(
connectionThreadLocal.get(), originalIsolation.get());
} finally {
connectionThreadLocal.remove();
originalIsolation.remove();
}
}
}