在开发了几个都具有与spring,hibernate和c3p0相似的设置作为connectionpool的webapp之后,我想研究一个我每次都注意到的问题: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组成-数据源和会话工厂:
<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>
当我启动webapp并查看jconsole的MBean或检查我的DBMS的开放连接时,我注意到c3p0建立的三个初始连接。
问题:当我告诉tomcat停止webapp时,它们仍然存在!
我创建了另一个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); } } }
但这是真的吗?没有我不知道的内置机制吗?
您是否尝试指定销毁方法?
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">