我最近开始在应用程序中使用hibernate和c3p0作为ORM。但是,当我关闭会话工厂时,连接池不会自行关闭!这是我的应用程序中 唯一 可以进行会话操作的地方。
StatelessSession session = null; Transaction transaction = null; try { session = sessionFactory.openStatelessSession(); transaction = session.beginTransaction(); List<Thingy> list = session.getNamedQuery("getAvailableThingy").list(); transaction.commit(); return list; } catch (Exception error) { if (transaction != null) { transaction.rollback(); } throw error; } finally { if (session != null) { session.close(); } }
这是我的hibernate.cfg.xml配置文件
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">org.postgresql.Driver</property> <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property> <property name="javax.persistence.validation.mode">none</property> <property name="hibernate.connection.release_mode">after_transaction</property> <property name="hibernate.c3p0.minPoolSize">1</property> <property name="hibernate.c3p0.maxPoolSize">2</property> <property name="hibernate.c3p0.acquireIncrement">1</property> <property name="hibernate.c3p0.initialPoolSize">1</property> <property name="hibernate.c3p0.timeout">30</property> <property name="hibernate.c3p0.maxIdleTimeExcessConnections">5</property> <property name="hibernate.c3p0.idleConnectionTestPeriod">300</property> </session-factory> </hibernate-configuration>
请注意,空闲连接非常短的原因是它是我尚未通过集成测试的唯一方法。他们经常打开和关闭会话工厂,因此我总是用尽所有连接。正如我们在项目开始时一样,从长远来看,我认为这不是一个非常可持续的策略。
需要注意的“有趣”是,尽管我将初始连接池设置为一个,但c3p0仍然尝试在启动时打开两个连接。我的猜测是某个隐藏的会话在某个地方不会关闭(但是在哪里?击败了我)。
那么,如何才能使那个烦人的连接池关闭呢?
附加信息:我如何创建和销毁会话工厂
import static com.google.common.base.Preconditions.*; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Provides; @Singleton public class PostgisConnection implements Provider<SessionFactory>, AutoCloseable { private final Logger logger = LoggerFactory.getLogger(getClass()); private final ConnectionInfo connectionInfo; private SessionFactory sessionFactory = null; @Inject public PostgisConnection(ConnectionInfo connectionInfo) { this.connectionInfo = connectionInfo; } public AutoCloseable open() { checkState(sessionFactory == null, "Connections to postgis are already open"); logger.info("Creating sessionFactory for connection to postgis: {}", connectionInfo.getJdbcUrl()); sessionFactory = newPostgisSessionFactory(connectionInfo); return this; } @Override public void close() throws Exception { try { if (sessionFactory != null) { logger.info("Closing sessionFactory for postgis: {}", connectionInfo.getJdbcUrl()); sessionFactory.close(); checkState(sessionFactory.isClosed(), "Session factory should be closed at this point"); } } catch (Exception error) { logger.error("Error closing SessionFactory", error); } } @Provides public SessionFactory get() { return sessionFactory; } public static SessionFactory newPostgisSessionFactory(ConnectionInfo connectionInfo) { Configuration configuration = configurationWith(connectionInfo); return configuration.buildSessionFactory(registryFrom(configuration)); } private static Configuration configurationWith(ConnectionInfo connectionInfo) { Configuration configuration = new Configuration(); setConnectionInfo(connectionInfo, configuration); configuration.addURL(PostgisConnection.class.getResource("mapping.hbm.xml")); configuration.configure(PostgisConnection.class.getResource("hibernate.cfg.xml")); return configuration; } private static void setConnectionInfo(ConnectionInfo connectionInfo, Configuration configuration) { configuration.setProperty("hibernate.connection.url", connectionInfo.getJdbcUrl()); configuration.setProperty("hibernate.connection.username", connectionInfo.getUsername()); configuration.setProperty("hibernate.connection.password", connectionInfo.getPassword()); } private static ServiceRegistry registryFrom(Configuration configuration) { return new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); } }
我遇到了同样的问题,并成功使用了此错误报告中提供的解决方法:
private void closeSessionFactory(SessionFactory factory) { if(factory instanceof SessionFactoryImpl) { SessionFactoryImpl sf = (SessionFactoryImpl)factory; ConnectionProvider conn = sf.getConnectionProvider(); if(conn instanceof C3P0ConnectionProvider) { ((C3P0ConnectionProvider)conn).close(); } } factory.close(); }
您必须引用hibernate-c3p0-4.xx jar。