2012-11-23 36 views
5

कई वेबपैप्स विकसित करने के बाद वसंत, हाइबरनेट और सी 3 पी 0 के साथ कनेक्शनपूल के रूप में एक समान सेटअप था, मैं किसी समस्या की जांच करना चाहता था जिसे मैंने हर बार देखा: कनेक्शंस कनेक्शन को तब तक रखता है जब तक आप टॉमकैट (या आपका एप्लिकेशन सर्वर) बंद नहीं करते।संदर्भ अनलोड पर कनेक्शन पूल को कैसे बंद करें?

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

(प्लस विशिष्ट JDBC ड्राइवर):

आज मैं सबसे बुनियादी परियोजना मैं कर सकता इन चार निर्भरता के साथ पैदा करते हैं।

मेरा वेब.एक्सएमएल केवल एक कॉन्टेक्स्टलोडर लिस्टर बनाता है जो एप्लिकेशन संदर्भ सेट करता है।

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

जब मैं webapp और या तो JConsole के MBeans पर गौर या खुले कनेक्शनों के लिए मेरे डीबीएमएस जाँच मैं तीन प्रारंभिक कनेक्शन नोटिस शुरू c3p0 द्वारा बनाया गया।

समस्या: जब मैं वेबैप को रोकने के लिए टोमकैट बताता हूं, तब भी वे रहते हैं!

मैंने एक और ServletContextListener बनाया है जिसमें केवल संदर्भ है, प्रोस्ट्राइड विधि लागू की गई है और प्रोग्रामेटिक रूप से सत्र को बंद कर देती है फैक्ट्री (और जेडीबीसी ड्राइवरों को भी अपमानित करता है जो स्वचालित रूप से नहीं किया जाता है)। कोड है:

@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

क्या आपने विनाश-विधि निर्दिष्ट करने का प्रयास किया है?

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

अनुभव के रूप में मूल्यवान कुछ भी नहीं है ... यह काम करता है! धन्यवाद (लेकिन jdbc ड्राइवर के बारे में क्या पंजीकरण नहीं है?) – realsim

+1

ड्राइवरों का पंजीकरण करने से उन्हें 'DriverManager' की आंतरिक स्थैतिक सूची से हटा दिया जाता है। अगली बार जब कनेक्शन पूल एक नया संसाधन हासिल करना चाहता है, तो यह इसके लिए 'ड्राइवर प्रबंधक' पूछता है। लेकिन अगर कनेक्शन पहले से ही अधिग्रहित किया गया था और पूल में रहता है, तो कुछ भी इसे काम जारी रखने से रोकता है। बीटीडब्लू, यह क्लास लोडर मेमोरी लीक में भी परिणाम देता है क्योंकि कनेक्शन पूल थ्रेड्स ने कक्षाओं को नष्ट नहीं होने दिया। कृपया, अगर आपको लगता है कि आपके पास और प्रश्न नहीं हैं तो प्रश्न हल करें। –

+0

@realsim: इस उत्तर को स्वीकार करने के लिए मत भूलना! –