after developing several webapps that all had a similar setup with spring, hibernate and c3p0 as connectionpool I wanted to investigate a problem that i noticed everytime: Connectionpool keeps the connections until you shutdown tomcat (or your application server).
Today i create the most basic project I could with these four dependencies:
org.springframework:spring-web
org.springframework:spring-orm
org.hibernate:hibernate-core
c3p0:c3p0
(plus the specific JDBC driver).
My web.xml only creates a ContextLoaderListener that sets up the application context.
<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>
application context consists of two beans - datasource and session factory:
<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>
When i start the webapp and either look into jconsole's MBeans or check my DBMS for open connections i notice the three initial connections made by c3p0.
PROBLEM: When i tell tomcat to stop the webapp, they still remain!
I created another ServletContextListener that only has the contextDestroyed method implemented and programatically shuts down the sessionFactory (and also deregisters the JDBC drivers which is also not done automatically). Code is:
@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);
        }
    }
}
But is that really it? Is there no built-in mechanism that I am not aware of?
Have you tried to specify the destroy-method?
<bean class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With