2012-11-23 32 views
5

sau khi phát triển một số ứng dụng web mà tất cả đều có thiết lập tương tự với spring, hibernate và c3p0 như connectionpool tôi muốn điều tra sự cố mà tôi nhận thấy mọi lúc: Connectionpool giữ kết nối cho đến khi bạn tắt tomcat (hoặc máy chủ ứng dụng của bạn).Cách tắt hồ bơi kết nối khi dỡ tải ngữ cảnh?

Hôm nay tôi tạo ra các dự án cơ bản nhất mà tôi có thể với bốn phụ thuộc:

org.springframework:spring-web 
org.springframework:spring-orm 
org.hibernate:hibernate-core 
c3p0:c3p0 

(cộng với trình điều khiển JDBC cụ thể).

Web.xml của tôi chỉ tạo ContextLoaderListener để thiết lập ngữ cảnh ứng dụng.

<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> 

ứng dụng bối cảnh gồm hai đậu - nguồn dữ liệu và phiên nhà máy:

<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> 

Khi tôi bắt đầu webapp và một trong hai nhìn vào MBeans jconsole hoặc kiểm tra DBMS của tôi cho các kết nối mở tôi nhận thấy ba kết nối ban đầu được thực hiện bởi c3p0.

VẤN ĐỀ: Khi tôi yêu cầu tomcat ngừng sử dụng webapp, chúng vẫn giữ nguyên!

Tôi đã tạo một ServletContextListener khác chỉ có phương thức contextDestroyed được thực hiện và lập trình tắt sessionFactory (và cũng hủy đăng ký các trình điều khiển JDBC cũng không được thực hiện tự động). Mã số:

@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); 
     } 
    } 
} 

Nhưng đó thực sự là nó? Không có cơ chế tích hợp mà tôi không biết?

Trả lời

12

Bạn đã cố gắng chỉ định phương thức hủy không?

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

Không có gì có giá trị như trải nghiệm ... nó hoạt động! Cảm ơn bạn (nhưng những gì về trình điều khiển jdbc unregistering?) – realsim

+1

Deregistering của trình điều khiển chỉ cần loại bỏ chúng từ danh sách tĩnh nội bộ của 'DriverManager'. Khi hồ bơi kết nối thời gian tiếp theo muốn có được một tài nguyên mới, nó sẽ hỏi 'DriverManager' cho nó. Nhưng nếu kết nối đã được mua lại và ở lại trong hồ bơi, thì không có gì ngăn cản nó tiếp tục hoạt động. BTW, điều này cũng dẫn đến rò rỉ bộ nhớ Class Loader vì các chủ đề của pool kết nối không cho phép các lớp bị phá hủy. Vui lòng đánh dấu câu hỏi là đã được giải quyết nếu bạn cảm thấy bạn không có thêm câu hỏi nào. –

+0

@realsim: đừng quên chấp nhận câu trả lời này! –

Các vấn đề liên quan