This subject has been discussed a zillion times on the web (not always very constructive) and it has been bothering me for many years as well. So let me be person zillion+1 to write a blog entry on it.
Let me first describe my setup: Tomcat 5.5, MySQL Ver 14.12 Distrib 5.0.51a, for debian-linux-gnu (x86_64) , mysql-connector-java-3.0.17-ga, c3p0 0.8.5.2, hibernate 3.2. In my application I access the database both via hibernate and via tomcat container managed authentication.
In mysql the configuration parameter wait_timeout defaults to 28800 seconds (= 8 hours), typically resulting - if no precautions are taken - in an sql exception after a night of inactivity on the webapp. What can be done about this:
- increase this timeout value in my.cnf (make sure to change it in the mysqld section), but this is a workaround and not a real solution.
- use the connection testing mechanisms provided by e.g. the c3p0 pooling lib.
A good description of this connection testing is provided here . The most robust mechanism is testing the connection before you want to use it (testConnectionOnCheckout), so let’s focus on this approach for the remainder of this article.
What we need to figure out now is how we configure c3p0 pools with the testConnectionOnCheckout mechanism in hibernate and in container-based authentication (because these are the 2 ways we access the database)
For hibernate I used following fragment in the hibernate config file
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.max_size">4</property>
<property name="hibernate.c3p0.min_size">2</property>
<property name="hibernate.c3p0.timeout">200</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="hibernate.c3p0.acquire_increment">1</property>
AFAIK the explicit mentioning of connection.provider_class is only needed for hibernate 3.3 and higher.
I also added following c3p0.properties file on the class path:
c3p0.testConnectionOnCheckout=true
c3p0.preferredTestQuery = SELECT 1
c3p0.checkoutTimeout = 10000
For the container-based authentication I added following DataSource and Realm in the context of server.xml
<Resource name="jdbc/myAppDs" auth="Container" type="com.mchange.v2.c3p0.ComboPooledDataSource"
driverClass="com.mysql.jdbc.Driver"
factory="org.apache.naming.factory.BeanFactory"
jdbcUrl="jdbc:mysql://localhost/myAppt"
user="aUser"
password="aPassword"
minPoolSize="5"
maxPoolSize="15"
maxIdleTime="200"
acquireIncrement="3"/>
<Realm className="org.apache.catalina.realm.DataSourceRealm"
debug="99"
dataSourceName="myAppDs"
localDataSource="true"
digest="md5"
userTable="userPswd"
userNameCol="username"
userCredCol="password"
userRoleTable="userRole"
roleNameCol="role" />
The resource also needs to be specified in the corresponding web.xml
<resource-ref>
<res-ref-name>jdbc/myAppDs</res-ref-name>
<res-type>com.mchange.v2.c3p0.ComboPooledDataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
So, that’s how I am avoiding the daily sql exceptions …