ayúdame a evitar el tiempo de espera de conexión con JPA, Hibernate y MySQL

Estoy usando JPA (Hibernate como proveedor), Glassfish y MySQL. Todo funciona muy bien en el desarrollo, pero cuando implemento la aplicación en un servidor de prueba y la dejo ejecutar (en gran parte inactiva) durante la noche, generalmente me saludan por la mañana:

[#|2011-03-09T15:06:00.229+0000|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=23;_ThreadName=Thread-1;|ERROR [htt\
p-thread-pool-8080-(1)] (JDBCTransaction.java:91) - JDBC begin failed
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 41,936,868 milliseconds ago.  The last packet \
sent successfully to the server was 41,936,868 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expirin\
g and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connec\
tion property 'autoReconnect=true' to avoid this problem.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
        at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1118)
        at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3321)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1940)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2562)
        at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:4956)
        at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:87)
        at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)
        at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:60)

Intenté usar lo siguiente en mipersistence.xml, pero no ayudó:

        <property name="hibernate.c3p0.min_size" value="5"/>
        <property name="hibernate.c3p0.max_size" value="20"/>
        <property name="hibernate.c3p0.idleTestPeriod" value="30"/>
        <property name="hibernate.c3p0.timeout" value="0"/>
        <property name="hibernate.c3p0.max_statements" value="0"/>

Así que esa es la configuración C3p0; es muy posible que me falte la parte que realmente dice hibernate "oye, usa c3p0".

Estoy a punto de probar la sugerencia que aparece en el mensaje de error: agregueautoReconnect=true a mi URL de JDBC, pero en este momento esto realmente comienza a parecer un desarrollo de culto de carga. Agradecería alguna orientación sobre la forma correcta de abordar este problema. Es difícil de depurar, porque el ciclo de prueba es efectivamente "ejecutarlo durante la noche, ver qué pasa en la mañana".

Probablemente debería mencionar cómo estoy usando conexiones en mi aplicación. Tengo una @ personalizaServlet Filter que intercepta todas las solicitudes. Crea un EntityManager, lo almacena en un ThreadLocal y el filtro lo cierra en un bloque catch / finalmente. Todas mis entidades obtienen una referencia a laEntityManager desde elThreadLocal.

Es completamente posible que mi filtro tenga la culpa, pero como solo parece suceder después de períodos inactivos, sospecho que algo más está mal. Tengo la intención de pasar a Seam / Weld cuando tenga la oportunidad de recuperar el aliento, pero por ahora confío en este filtro.

Edit: aquí está la solución TL; DR:

Utilice el grupo de conexiones de su contenedor, si puede (gracias, @partenon) asegúrese de que su grupo de conexiones use validación de conexión (gracias, @matt b)

En mi caso, tuve que ir a la consola de Glassfish en Recursos / JDBC / Grupos de conexiones, pestaña Avanzado, y luego habilitar la Validación de conexión:

Este fue realmente el paso crucial. También es probable que desee establecerValidate At Most Once a algo razonable, digamos 100 segundos. Si está utilizando C3P0 o similar, asegúrese de configuraridle_test_period ypreferredTestQuery.

Sea lo que sea que termines haciendo, es importante probar tus cambios para ver si tienen el efecto deseado. Para acelerar el tiempo de espera en MySQL, puede configurar temporalmente elwait_timeout a algo bajo como 30 segundos editandomy.cnf. Esta fue una gran ayuda para depurar este problema, ya que me permitió probar los cambios en segundos, en lugar de horas.

Respuestas a la pregunta(4)

Su respuesta a la pregunta