Revert "Automatically close SessionFactory objects"

This reverts commit bb4f48dcb3.

Issue: SPR-8114
This commit is contained in:
Chris Beams 2011-10-09 07:55:28 +00:00
parent b82d5ae8da
commit 1a8531b401
6 changed files with 28 additions and 94 deletions

View File

@ -19,9 +19,7 @@ package org.springframework.orm.hibernate3;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.List;
@ -36,7 +34,6 @@ import org.hibernate.classic.Session;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -130,16 +127,6 @@ public class HibernateSessionFactoryConfigurationTests {
}
}
@Test
public void builtSessionFactoryIsDisposableBeanProxy() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AnnotationSessionFactoryConfig.class);
SessionFactory sessionFactory = ctx.getBean(SessionFactory.class);
assertThat(sessionFactory, instanceOf(DisposableBean.class));
assertThat(sessionFactory.toString(), startsWith("DisposableBean proxy for SessionFactory"));
ctx.close();
assertTrue("SessionFactory was not closed as expected", sessionFactory.isClosed());
}
private void saveAndRetriveEntity(Class<?> configClass) {
SessionFactory sessionFactory = new AnnotationConfigApplicationContext(configClass).getBean(SessionFactory.class);

View File

@ -17,8 +17,8 @@
package org.springframework.orm.hibernate3;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.support.SQLExceptionTranslator;
@ -110,11 +110,6 @@ public class LocalSessionFactoryBean extends SessionFactoryBuilder implements Se
delegate.setPersistenceExceptionTranslator(hibernateExceptionTranslator);
}
@Override
public SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) {
return delegate.wrapSessionFactoryIfNecessary(rawSf);
}
/**
* @deprecated as of Spring 3.1 in favor of {@link #newSessionFactory()} which
* can access the internal {@code Configuration} instance via {@link #getConfiguration()}.

View File

@ -16,6 +16,8 @@
package org.springframework.orm.hibernate3;
import javax.sql.DataSource;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cache.RegionFactory;
@ -113,7 +115,23 @@ public class SessionFactoryBeanDelegate implements SessionFactoryBeanOperations
}
public void destroy() throws HibernateException {
SessionFactoryBuilderSupport.closeHibernateSessionFactory(this.builder, this.sessionFactory);
builder.logger.info("Closing Hibernate SessionFactory");
DataSource dataSource = builder.getDataSource();
if (dataSource != null) {
// Make given DataSource available for potential SchemaExport,
// which unfortunately reinstantiates a ConnectionProvider.
SessionFactoryBuilderSupport.configTimeDataSourceHolder.set(dataSource);
}
try {
builder.beforeSessionFactoryDestruction();
}
finally {
this.sessionFactory.close();
if (dataSource != null) {
// Reset DataSource holder.
SessionFactoryBuilderSupport.configTimeDataSourceHolder.remove();
}
}
}
public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
@ -124,11 +142,6 @@ public class SessionFactoryBeanDelegate implements SessionFactoryBeanOperations
return hibernateExceptionTranslator.translateExceptionIfPossible(ex);
}
public SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) {
return rawSf;
}
/**
* @see SessionFactoryBuilderSupport#preBuildSessionFactory()
*/

View File

@ -125,12 +125,4 @@ public interface SessionFactoryBeanOperations
*/
DataAccessException translateExceptionIfPossible(RuntimeException ex);
/**
* Override the default {@link DisposableBean} proxying behavior in
* {@link SessionFactoryBuilderSupport#wrapSessionFactoryIfNecessary(SessionFactory)}
* and return the raw {@code SessionFactory} instance, as {@link SessionFactory#close()}
* will be called during this FactoryBean's normal {@linkplain #destroy() destruction lifecycle}.
*/
SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf);
}

View File

@ -18,9 +18,7 @@ package org.springframework.orm.hibernate3;
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
@ -34,7 +32,6 @@ import javax.transaction.TransactionManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Session;
@ -48,10 +45,7 @@ import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.event.EventListeners;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
import org.hibernate.transaction.JTATransactionFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
@ -546,37 +540,16 @@ public abstract class SessionFactoryBuilderSupport<This extends SessionFactoryBu
}
/**
* Wrap the given {@code SessionFactory} with a proxy, if demanded.
* <p>The default implementation wraps the given {@code SessionFactory} as a Spring
* {@link DisposableBean} proxy in order to call {@link SessionFactory#close()} on
* {@code ApplicationContext} {@linkplain ConfigurableApplicationContext#close() shutdown}.
* <p>Subclasses may override this to implement transaction awareness through
* a {@code SessionFactory} proxy for example, or even to avoid creation of the
* {@code DisposableBean} proxy altogether.
* @param rawSf the raw {@code SessionFactory} as built by {@link #buildSessionFactory()}
* @return the {@code SessionFactory} reference to expose
* Wrap the given SessionFactory with a proxy, if demanded.
* <p>The default implementation simply returns the given SessionFactory as-is.
* Subclasses may override this to implement transaction awareness through
* a SessionFactory proxy, for example.
* @param rawSf the raw SessionFactory as built by {@link #buildSessionFactory()}
* @return the SessionFactory reference to expose
* @see #buildSessionFactory()
*/
protected SessionFactory wrapSessionFactoryIfNecessary(final SessionFactory rawSf) {
return (SessionFactory) Proxy.newProxyInstance(
this.beanClassLoader,
new Class<?>[] {
SessionFactory.class,
DisposableBean.class
},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (ReflectionUtils.isToStringMethod(method)) {
return String.format("DisposableBean proxy for SessionFactory [%s]", rawSf.toString());
}
if (method.equals(DisposableBean.class.getMethod("destroy"))) {
closeHibernateSessionFactory(SessionFactoryBuilderSupport.this, rawSf);
rawSf.close();
return null;
}
return method.invoke(rawSf, args);
}
});
protected SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) {
return rawSf;
}
/**
@ -1424,24 +1397,4 @@ public abstract class SessionFactoryBuilderSupport<This extends SessionFactoryBu
return configTimeLobHandlerHolder.get();
}
static void closeHibernateSessionFactory(SessionFactoryBuilderSupport<?> builder, SessionFactory sessionFactory) {
builder.logger.info("Closing Hibernate SessionFactory");
DataSource dataSource = builder.getDataSource();
if (dataSource != null) {
// Make given DataSource available for potential SchemaExport,
// which unfortunately reinstantiates a ConnectionProvider.
SessionFactoryBuilderSupport.configTimeDataSourceHolder.set(dataSource);
}
try {
builder.beforeSessionFactoryDestruction();
}
finally {
sessionFactory.close();
if (dataSource != null) {
// Reset DataSource holder.
SessionFactoryBuilderSupport.configTimeDataSourceHolder.remove();
}
}
}
}

View File

@ -18,7 +18,6 @@ package org.springframework.orm.hibernate3.annotation;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternUtils;
@ -135,11 +134,6 @@ public class AnnotationSessionFactoryBean extends AnnotationSessionFactoryBuilde
delegate.setPersistenceExceptionTranslator(hibernateExceptionTranslator);
}
@Override
public SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) {
return delegate.wrapSessionFactoryIfNecessary(rawSf);
}
/**
* @deprecated as of Spring 3.1 in favor of {@link #scanPackages()} which
* can access the internal {@code AnnotationConfiguration} instance via