2012-11-23 30 views
5

在開發了幾個webapps之後,所有的webapps都和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> 

當我開始的Web應用程序,要麼考慮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); 
     } 
    } 
} 

不過是真的嗎?有沒有我不知道的內置機制?

回答

12

您是否試過指定destroy方法?

<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 
+0

沒有什麼和經驗一樣有價值了......它的工作!謝謝(但是jdbc驅動註銷怎麼樣?) – realsim

+1

取消註冊驅動只是將它們從'DriverManager'的內部靜態列表中刪除。當下一次連接池想要獲取新資源時,它會詢問'DriverManager'。但是,如果連接已經獲得並留在游泳池中,那麼沒有任何東西阻止它繼續工作。順便說一句,這也會導致Class Loader內存泄漏,因爲連接池線程不會讓類被銷燬。如果您覺得您沒有其他問題,請將問題標記爲已解決。 –

+0

@realsim:不要忘記接受這個答案! –