Hibernate – C3P0 Connection Pooling

By default, Hibernate uses JDBC connections in order to interact with a database. Creating these connections is expensive, probably the most expensive, single operation Hibernate will execute in a typical usecase. For this reason, we are advised to use a connection pool, which can store open connections ahead of time and close them only when they are not needed.

Thankfully, Hibernate is designed to use a connection pool by default, an internal implementation. However, Hibernate’s built-in connection pooling isn’t designed for production use. In production, we would use an external connection pool by using either a database connection provided by JNDI or an external connection pool configured via parameters and classpath.

C3P0 is an example of an external connection pool. In this tutorial, we will learn using C3P0 with hibernate.

Table of Contents

1. Maven dependencies
2. Configure C3P0 Connection Pool with Hibernate
3. Debug connection leaks
3. Test connection pooling in runtime

1. Maven dependencies

To configure c3p0 with hibernate, we need to add c3p0 and Hibernate’s c3p0 connection provider hibernate-c3p0 as dependencies in the pom.xml.

Please note that the version of the hibernate-c3p0 dependency should match the Hibernate’s compatible version.

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-c3p0</artifactId>
    <version>5.4.17.Final</version>
</dependency>
<dependency>
	<groupId>c3p0</groupId>
	<artifactId>c3p0</artifactId>
	<version>0.9.5.3</version>
</dependency>

2. Configuring C3P0 with Hibernate

The best part is that the configuration of C3P0 with hibernate is really very easy. Just add any c3p0 property inside the hibernate.cfg.xml file and that’s it.

<property name="hibernate.c3p0.min_size">10</property>

Congratulations !! Connection pooling with C3P0 is now configured with the application’s hibernate layer. We are good to start testing the things. Really easy, Isn’t it?

A rather detailed configuration can be setup using following properties in hibernate.cfg.xml. All keys are prefixed with hibernate.c3p0.

<property name="hibernate.c3p0.min_size">10</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.validate">1800</property>

We can find detailed information about about above configuration switches in official documentation.

3. Debug connection leaks

Sometimes applications talk to many other applications and some applications or interactions take a longer time to respond. This can overwhelm the connection pool (when the pool grows to maxPoolSize) and degrade the performance of the whole application.

c3p0 can help us debug the pool where connections have been checked out and don’t get checked in.

<property name="hibernate.c3p0.unreturnedConnectionTimeout">30</property>
<property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces">true</property>

unreturnedConnectionTimeout helps in fixing leaks. It defines time (in seconds) to how long a Connection may remain checked out. Checked-out Connections that exceed this limit will be destroyed, and then created a new one in the pool.

debugUnreturnedConnectionStackTraces helps in debugging the root cause. when set to true, whenever an unreturned Connection times out, that stack trace will be printed, revealing where a Connection was checked out that was not checked in.

4. Testing connection pool in runtime

4.1. Without C3P0 Connection Pool Configuration

Without C3P0 configured, if you see the debug logs of hibernate, you will see something like this:

DEBUG Configuration:1841 - Preparing to build session factory with filters : {}
WARN DriverManagerConnectionProviderImpl:93 - HHH000402: Using Hibernate built-in connection pool (not for production use!)
INFO DriverManagerConnectionProviderImpl:166 - HHH000401: using driver [org.hsqldb.jdbcDriver] at URL [jdbc:hsqldb:mem:howtodoinjava]
INFO DriverManagerConnectionProviderImpl:172 - HHH000046: Connection properties: {user=sa, password=}
INFO DriverManagerConnectionProviderImpl:180 - HHH000006: Autocommit mode: false
INFO DriverManagerConnectionProviderImpl:102 - HHH000115: Hibernate connection pool size: 20 (min=1)
DEBUG DriverManagerConnectionProviderImpl:104 - Initializing Connection pool with 1 Connections
...
...
...
EBUG JdbcTransaction:113 - committed JDBC Connection
DEBUG SessionFactoryImpl:1339 - HHH000031: Closing
DEBUG AbstractServiceRegistryImpl:406 - Implicitly destroying ServiceRegistry on de-registration of all child ServiceRegistries
INFO DriverManagerConnectionProviderImpl:281 - HHH000030: Cleaning up connection pool [jdbc:hsqldb:mem:howtodoinjava]

4.2. Using C3P0 Connection Pool Configuration

After configuring C3P0 Connection Pool, you will be able to see in the logs that connections are now acquired from C3P0 Connection Pool itself.

DEBUG Configuration:1841 - Preparing to build session factory with filters : {}
 INFO C3P0ConnectionProvider:133 - HHH010002: C3P0 using driver: org.hsqldb.jdbcDriver at URL: jdbc:hsqldb:mem:howtodoinjava
 INFO C3P0ConnectionProvider:134 - HHH000046: Connection properties: {user=sa, password=****}
 INFO C3P0ConnectionProvider:137 - HHH000006: Autocommit mode: false
 INFO MLog:92 - MLog clients using log4j logging.
 INFO C3P0Registry:216 - Initializing c3p0-0.9.2.1 [built 20-March-2013 10:47:27 +0000; debug? true; trace: 10]
DEBUG DynamicPooledDataSourceManagerMBean:258 - MBean: com.mchange.v2.c3p0:type=PooledDataSource,identityToken=19tu9of94ho8s13xij3fm|34e475e1,name=19tu9of94ho8s13xij3fm|34e475e1 registered.
DEBUG DynamicPooledDataSourceManagerMBean:253 - MBean: com.mchange.v2.c3p0:type=PooledDataSource,identityToken=19tu9of94ho8s13xij3fm|34e475e1,name=19tu9of94ho8s13xij3fm|34e475e1 unregistered, in order to be reregistered after update.
DEBUG DynamicPooledDataSourceManagerMBean:258 - MBean: com.mchange.v2.c3p0:type=PooledDataSource,identityToken=19tu9of94ho8s13xij3fm|34e475e1,name=19tu9of94ho8s13xij3fm|34e475e1 registered.
 INFO AbstractPoolBackedDataSource:522 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@d29bbf50 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@a9bbd924 [ ... ]
 ...
 ...
 ...
 DEBUG ActiveManagementCoordinator:97 - C3P0Registry mbean unregistered.
DEBUG BasicResourcePool:1022 - Preparing to destroy resource: com.mchange.v2.c3p0.impl.NewPooledConnection@1d1fcfbb
DEBUG C3P0PooledConnectionPool:616 - Preparing to destroy PooledConnection: com.mchange.v2.c3p0.impl.NewPooledConnection@1d1fcfbb
DEBUG AbstractPoolBackedDataSource:477 - com.mchange.v2.c3p0.PoolBackedDataSource@34e475e1 has been closed. 
java.lang.Exception: DEBUG STACK TRACE for PoolBackedDataSource.close().
	at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.close(AbstractPoolBackedDataSource.java:477)
	at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.close(AbstractPoolBackedDataSource.java:489)
	at com.mchange.v2.c3p0.DataSources.destroy(DataSources.java:372)
	at com.mchange.v2.c3p0.DataSources.destroy(DataSources.java:348)
	at org.hibernate.c3p0.internal.C3P0ConnectionProvider.stop(C3P0ConnectionProvider.java:258)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.stopService(AbstractServiceRegistryImpl.java:377)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.destroy(AbstractServiceRegistryImpl.java:361)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.deRegisterChild(AbstractServiceRegistryImpl.java:410)
	at org.hibernate.service.internal.AbstractServiceRegistryImpl.destroy(AbstractServiceRegistryImpl.java:368)
	at org.hibernate.internal.SessionFactoryImpl.close(SessionFactoryImpl.java:1377)
	at com.howtodoinjava.demo.util.HibernateUtil.shutdown(HibernateUtil.java:39)
	at com.howtodoinjava.test.TestHibernate.main(TestHibernate.java:22)

That’s all for this easy but useful tutorial about configuring C3P0 Connection Pool with hibernate.

Happy Learning !!

Reference: http://www.mchange.com/projects/c3p0/#configuration

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

5 thoughts on “Hibernate – C3P0 Connection Pooling”

  1. Hi
    I have configured c3p0 with Hibernate. It works fine till connections get exhausted to max limit. Then it stops providing responses. So, practically, my web app does not receive any data. No errors in console.

    Tried with “org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider” also.

    My sessionFactory creation class is as below:

    public class DBConfiguration {
    	
    	private static SessionFactory sessionFactory = setSessionFactory();
    	 
    	private static SessionFactory setSessionFactory() {
        	Configuration configuration = null; 
        	configuration = new Configuration().configure("hibernate.cfg.xml");
        	StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
    
            return configuration.buildSessionFactory(builder.build());
        }
     
        public static SessionFactory getSessionFactory() {
        	if(sessionFactory == null) {
        		sessionFactory = setSessionFactory();
        	}
            return sessionFactory;
        }
        
        public static void closeSessionFactory() {
        	sessionFactory.close();
        }
    }
    

    I have done session.flush() and session.close() after every DB queries.

    It seems that the connection is not released from the pool for another client to use. Hence after the max number of connections is reached, it is waiting for one to be released, which is not happening.

    I tried with 50 as max limit, it stays for longer than stops.

    Am I missing something?

    Reply
  2. Is it possible to modify all properties at runtime? For instance, if I encounter that the value of maximum connections needs to be increased, can I do this without re-starting the CP?

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.