Manejo elegante de conexiones obsoletas de bases de datos en Hibernate/Spring Transactions

tengo un sistema que ha estado funcionando bien en las pruebas, pero ahora que lo he movido a los servidores de producción y estoy listo para cambiar, tengo un problema.

si la aplicación permanece inactiva durante unos 15 minutos, se cae la conexión de la base de datos en el servicio de transacciones Spring. la primera persona que llega a la aplicación después de que eso suceda es saludada con esto

org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Cannot open connection
    org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:596)
    org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
    org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
    parity.persistence.DataAccess$$EnhancerByCGLIB$$921ef13.find(<generated>)
    parity.model.Configuration.getConfiguration(Configuration.java:84)
    parity.model.Configuration.getSetting(Configuration.java:46)
    parity.model.Configuration$$FastClassByCGLIB$$8355c3d0.invoke(<generated>)
    net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:617)
    parity.model.Configuration$$EnhancerByCGLIB$$5e96e8b9.getSetting(<generated>)
    parity.model.OnlineStatus.getSiteStatus(OnlineStatus.java:50)
    parity.action.site.SiteStatusInterceptor.intercept(SiteStatusInterceptor.java:16)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
    org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498)
    org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:434)
root cause

si presiona F5 en su navegador, se vuelve a conectar y funciona bien. parece que Spring está haciendo algo en la línea de la primera solicitud, pasando eek, morí, y en el proceso de morir, volviendo a conectarme a la base de datos. pero no estoy seguro.

He estado buscando formas de resolver esto, pero parece que, a menos que esté usando c3p0 o weblogic, todos no tienen ni idea. ¿Hay alguna manera de arreglar esto? aquí están mis archivos de configuración

hibernación.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="connection.autocommit">false</property>
        <property name="show_sql">false</property>
        <property name="use_sql_comments">false</property>

    </session-factory>
</hibernate-configuration>

transacción-servicio.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <bean id="boardingSessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocations">
            <list>
                <value>classpath:hibernate/boarding-hibernate.cfg.xml</value>
                <value>classpath:boarding-hibernate.cfg.xml</value>
            </list>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
    </bean>

    <bean id="boardingTransactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="boardingSessionFactory" />
        <qualifier value="boarding" />
    </bean>

    <tx:advice id="boardingTxAdvice" transaction-manager="boardingTransactionManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true" />
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>
</beans>

tenga en cuenta que mi hibernación usa 2 archivos, uno en la API que maneja la configuración global y otro en la aplicación en sí que tiene configuraciones específicas de la aplicación. para propósitos aquí, el global es todo lo que importa, creo.

preguntado el 03 de mayo de 12 a las 17:05

1 Respuestas

La Documentación de Hibernate dice:

El propio algoritmo de agrupación de conexiones de Hibernate es, sin embargo, bastante rudimentario. Su objetivo es ayudarlo a comenzar y no está diseñado para su uso en un sistema de producción, ni siquiera para pruebas de rendimiento. Debe usar un grupo de terceros para obtener el mejor rendimiento y estabilidad.

Entonces, la respuesta es simple: use un grupo de conexiones real y configúrelo para probar las conexiones antes de dárselas a la aplicación.

contestado el 03 de mayo de 12 a las 18:05

Tenía la impresión de que los servicios de transacción de primavera manejan la agrupación de conexiones, ¿me está diciendo que en realidad es hibernación la que maneja la agrupación? - scphantm

Lea esta sección de la documentación de Spring: static.springsource.org/spring/docs/3.1.x/…, así como este. Si no configura un DataSource, usando un grupo de conexiones, dentro de Spring, LocalSessionFactoryBean usará lo que configuró en el archivo de configuración de Hibernate, como se explica en el javadoc de LocalSessionFactoryBean: static.springsource.org/spring/docs/3.1.x/javadoc-api/org/… - JB Nizet

ugh, realmente desearía haber encontrado esto en las pruebas y no después de nuestro bloqueo de código. oh bueno, al menos implementar c3p0 no es un gran problema. - scphantm

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.