Hibernate / MySQL connection timeouts — Trying to deal with thread-pooled executors not releasing Hibernate connections to C3P0 after exit

南笙酒味 提交于 2019-12-05 06:03:10

NOTE: the below is based on an Oracle example, but can be modified for MySQL.

I have gotten around this problem of dropped connections by using Tomcat managed databased connections. This can be done by creating a context.xml file in your META-INF directory, something like this:

<Context crossContext="true" docBase="myBase" path="/myBase" reloadable="false" useHttpOnly="true">
    <ResourceLink global="jdbc/dbOne" name="jdbc/dbOne" type="javax.sql.DataSource" />
    <!-- Need another DB? -->   
    <!-- <ResourceLink global="jdbc/dbTwo" name="jdbc/dbTwo" type="javax.sql.DataSource" /> -->
</Context>

To create the connection your Tomcat server.xml file must also be updated. The below is based on Tomcat 6.0.26.:

<!-- Global JNDI resources
   Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
     UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
          type="org.apache.catalina.UserDatabase"
          description="User database that can be updated and saved"
          factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
          pathname="conf/tomcat-users.xml" />

    <!-- START MY MODS -->
    <!-- Add the db connection(s)! The rest is standard in the server.xml file.-->        
    <Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" initialSize="2" logAbandoned="true" maxActive="5" maxIdle="2" maxWait="120000" minEvictableIdleTimeMillis="1800000" minIdle="1" name="jdbc/dbOne" numTestsPerEvictionRun="3" password="openPlease" removeAbandoned="true" removeAbandonedTimeout="60" testOnBorrow="true" testOnReturn="true" testWhileIdle="true" timeBetweenEvictionRunsMillis="900000" type="javax.sql.DataSource" url="jdbc:oracle:thin:@servername:portnumber:schema" username="myUser" validationQuery="select sysdate from dual"/>  
    <!-- Need another connection? Copy and past the above making the required changes. -->
    <!-- END MY MODS -->

Then in my hibernate.cfg.xml file I have specified:

<!-- Connection handling -->
<property name="connection.datasource">java:/comp/env/jdbc/dbOne</property>
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="connection.autoReconnect">true</property>
<property name="connection.autoReconnectForPools">true</property>
<property name="connection.is-connection-validation-required">true</property>
<property name="current_session_context_class">thread</property>

Having said that, the following config using just C3P0 worked for me as well, but I now prefer Tomcat managed connections as they can be shared between the apps on my Tomcat server, which is desirable in my case.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="hibernate.connection.password">@dbPassword@</property>
        <property name="hibernate.connection.url">@dbURL@</property>
        <property name="hibernate.connection.username">someUser</property>
        <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>

        <property name="show_sql">false</property>
        <property name="format_sql">false</property>
        <property name="current_session_context_class">thread</property>

        <!-- Connection handling -->
        <property name="connection.autoReconnect">true</property>
        <property name="connection.autoReconnectForPools">true</property>
        <property name="connection.is-connection-validation-required">true</property>
        <property name="current_session_context_class">thread</property>
        <property name="max_fetch_depth">1</property>

        <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
        <property name="hibernate.c3p0.breakAfterAcquireFailure">false</property>
        <property name="hibernate.c3p0.acquireRetryAttempts">-1</property>
        <property name="hibernate.c3p0.acquireRetryDelay">3000</property>
        <property name="hibernate.c3p0.automaticTestTable">C3P0_TEST</property> <!-- c3p0 uses this table for testing connection. -->
        <property name="hibernate.c3p0.initialPoolSize">2</property> <!-- 3 is c3p0 default. -->
        <property name="hibernate.c3p0.minPoolSize">2</property> <!-- 1 is Hibernate default. -->
        <property name="hibernate.c3p0.maxPoolSize">6</property> <!-- 100 is Hibernate default. -->
        <property name="hibernate.c3p0.acquireIncrement">2</property> <!-- 3 is c3p0 default. -->
        <property name="hibernate.c3p0.maxIdleTimeExcessConnections">600</property> <!-- 0 seconds is c3p0 default and means do not check. This is the num of seconds a connections in excess of minPoolSize are permitted to remain idle in the pool before being culled. -->
        <property name="hibernate.c3p0.idleConnectionTestPeriod">30</property> <!-- 0 seconds is the c3p0 default and means do not check. (i.e. never test). Using only this provides the best performance even if individuals may occasionally receive an error message due to a connection being dropped. -->

        <!-- Cache setup -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.use_query_cache">true</property>
        <property name="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</property>
       <!-- <property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</property> -->

        <property name="cache.use_minimal_puts">true</property>
        <property name="hibernate.generate_statistics">true</property>
        <property name="hibernate.cache.use_structured_entries">true</property>

        <!-- Mapping files -->
        ...

       </session-factory>

</hibernate-configuration>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!