1

我有一个使用 Spring 和 Hibernate 以及 mysql 数据库的 Web 应用程序。问题是,当应用程序启动一段时间并且长时间没有活动时,如果用户尝试登录,则会出现以下异常:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.JDBCConnectionException: could not execute query
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

root cause

org.hibernate.exception.JDBCConnectionException: could not execute query
org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
org.hibernate.loader.Loader.doList(Loader.java:2231)
org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
org.hibernate.loader.Loader.list(Loader.java:2120)
org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:118)
org.hibernate.impl.SessionImpl.list(SessionImpl.java:1596)
org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306)
com.smallworks.dao.impl.UserDAOImpl.getUserByLoginID(UserDAOImpl.java:102)
com.smallworks.authenticationService.impl.UserAuthenticationServiceImpl.isPasswordCorrect(UserAuthenticationServiceImpl.java:54)
com.smallworks.validation.UserLoginValidator.validate(UserLoginValidator.java:59)
com.smallworks.controller.ProjectController.signIn(ProjectController.java:84)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

root cause

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 33,781,083 milliseconds ago.  The last packet sent successfully to the server was 33,781,083 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
java.lang.reflect.Constructor.newInstance(Unknown Source)
com.mysql.jdbc.Util.handleNewInstance(Util.java:407)
com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3348)
com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1967)
com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2140)
com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2626)
com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2111)
com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2273)
org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
org.hibernate.loader.Loader.getResultSet(Loader.java:1808)
org.hibernate.loader.Loader.doQuery(Loader.java:697

并且用户尝试再次登录,它工作正常。

以下是我的 Hibernate 的配置:

<beans>   

<!-- ADD PERSISTENCE SUPPORT HERE (jpa, hibernate, etc) -->
 <tx:annotation-driven transaction-manager="transactionManager"/>

 <bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
    p:location="/WEB-INF/jdbc.properties" />

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="mappingResources">
        <list>
            <value>com/smallworks/model/User.hbm.xml</value>
            <value>com/smallworks/model/Contact.hbm.xml</value>
            <value>com/smallworks/model/Action.hbm.xml</value>
            <value>com/smallworks/model/Comment.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${jdbc.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.connection.autocommit">false</prop>
             <!--  -->   
            <prop key="hibernate.hbm2ddl.auto">update</prop>

        </props>
    </property>
    <property name="dataSource" ref="dataSource"/>
</bean>

 <bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean id="dataSource"
      class="org.apache.commons.dbcp.BasicDataSource"
      destroy-method="close"
      p:driverClassName="${jdbc.driverClassName}"
      p:url="${jdbc.url}"
      p:username="${jdbc.username}"
      p:password="${jdbc.password}" />

应用程序上下文.xml

 <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
                 <!--  -->   
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <!-- Managing connection -->
                <prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
                <prop key="c3p0.testConnectionOnCheckout">false</prop>
                <prop key="c3p0.min_size">5</prop>
                <prop key="c3p0.max_size">50</prop>
                <prop key="c3p0.timeout">300</prop>
                <prop key="c3p0.max_statements">50</prop>
                <prop key="c3p0.idleTestPeriod">300</prop>
            </props>
        </property>

我已经用上面的配置编辑了我的休眠配置,但它似乎仍然没有生效。任何正确方向的指导将不胜感激。

问候。

4

1 回答 1

2

这是您的数据库的超时,在一段时间后没有活动的每个连接都会被丢弃。您可以实现像 C3P0 这样的连接池管理器:

这是一个示例配置,可能会适应您的配置:

<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="c3p0.testConnectionOnCheckout">false</prop>
<prop key="c3p0.min_size">2</prop>
<prop key="c3p0.max_size">10</prop>
<prop key="c3p0.timeout">300</prop>
<prop key="c3p0.max_statements">50</prop>
<prop key="c3p0.idleTestPeriod">300</prop>

您只需要将C3P0中的 jar 添加到您的项目中。

于 2013-06-10T04:02:38.753 回答