Как отключить пул соединений при выгрузке контекста?
После разработки нескольких веб-приложений, в которых все были настроены с использованием Spring, Hibernate и C3p0 в качестве пула соединений, я захотел исследовать проблему, которую замечал каждый раз: Connectionpool сохраняет соединения до тех пор, пока вы не выключите Tomcat (или ваш сервер приложений).
Сегодня я создаю самый простой проект, который я могу, с этими четырьмя зависимостями:
org.springframework:spring-web
org.springframework:spring-orm
org.hibernate:hibernate-core
c3p0:c3p0
(плюс определенный драйвер JDBC).
Мой web.xml создает только ContextLoaderListener, который устанавливает контекст приложения.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
контекст приложения состоит из двух компонентов - источника данных и фабрики сеансов:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>org.postgresql.Driver</value>
</property>
<property name="jdbcUrl">
<value>jdbc:postgresql://localhost/mydb</value>
</property>
<property name="user">
<value>usr</value>
</property>
<property name="password">
<value>pwd</value>
</property>
</bean>
Когда я запускаю веб-приложение и либо просматриваю MBean-компоненты jconsole, либо проверяю мои СУБД на наличие открытых соединений, я замечаю три начальных соединения, выполненных c3p0.
ПРОБЛЕМА: Когда я говорю Tomcat, чтобы остановить веб-приложение, они все еще остаются!
Я создал еще один ServletContextListener, в котором реализован только метод contextDestroyed, и он программно завершает работу sessionFactory (а также отменяет регистрацию драйверов JDBC, что также не выполняется автоматически). Код является:
@Override
public void contextDestroyed(ServletContextEvent sce) {
...
sessionFactory().close();
// deregister sql driver(s)
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
log.info("deregistering jdbc driver: " + driver);
} catch (SQLException e) {
log.error("error deregistering jdbc driver: " + driver, e);
}
}
}
Но так ли это? Нет ли встроенного механизма, о котором я не знаю?