Hibernate异常:Spring升级后连接池耗尽错误

时间:2011-10-14 21:22:49

标签: hibernate spring tomcat spring-mvc apache-commons-dbcp

我在我的应用程序中使用Spring + Hibernate + Dbcp + Tomcat。由于某种原因,在最近的春季版本升级到3.0.6之后,应用程序开始抛出以下异常。

    org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.GenericJDBCException: Cannot open connection
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:596)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy7.findURLByPattern(Unknown Source)
at com.xxx.security.DAOBasedFilterInvocationDefinitionMap.lookupAttributes(DAOBasedFilterInvocationDefinitionMap.java:80)
at org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource.getAttributes(AbstractFilterInvocationDefinitionSource.java:39)
at org.acegisecurity.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:236)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:104)
at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.ntlm.HttpFilter.doFilter(HttpFilter.java:51)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:110)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:106)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:286)
at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:874)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:619)
    Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:420)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144)
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:119)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:57)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:551)
... 36 more
    Caused by: org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted, cause: Timeout waiting for idle object
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:148)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:518)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:417)
... 40 more
    Caused by: java.util.NoSuchElementException: Timeout waiting for idle object
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:801)
at org.apache.commons.dbcp.AbandonedObjectPool.borrowObject(AbandonedObjectPool.java:119)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:140)
... 43 more

我的配置如下

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db.driverClassName}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
    <property name="maxActive" value="10" />
    <property name="maxIdle" value="6" />
    <property name="maxWait" value="120" />
    <property name="defaultAutoCommit" value="true" />
    <property name="removeAbandoned" value="true" />
    <property name="removeAbandonedTimeout" value="60" />
</bean>

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

    <property name="configLocations">
        <list>
            <value>classpath:com/xxx/model/hibernate/hibernate-gas.cfg.xml</value>
        </list>
    </property>

    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect"> org.hibernate.dialect.SQLServerDialect </prop>
            <prop key="hibernate.jdbc.fetch_size">10</prop>
            <prop key="hibernate.jdbc.batch_size">50</prop>
            <prop key="hibernate.generate_statistics">true</prop>
        </props>
    </property>
</bean>

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


<bean id="myTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref local="sessionFactory" />
    </property>
    <property name="nestedTransactionAllowed" value="true" />
</bean>

<bean id="propagationRequired" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
        <ref bean="myTransactionManager" />
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="select*">
                PROPAGATION_REQUIRED,readOnly, timeout_300
            </prop>
            <prop key="search*">
                PROPAGATION_REQUIRED,readOnly, timeout_300
            </prop>
            <prop key="*">
                PROPAGATION_REQUIRED, timeout_300,
                -Exception
            </prop>
        </props>
    </property>
</bean>

<bean id="propagationRequiresNew" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
        <ref bean="transactionManager" />
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="*">
                PROPAGATION_REQUIRES_NEW, timeout_300,
                -Exception
            </prop>
        </props>
    </property>
</bean>

3 个答案:

答案 0 :(得分:0)

通常我会说尝试c3p0(不同的连接池实现)。

但是,我认为问题在于您的应用程序如何处理数据库连接。 我有兴趣了解您为dbcp连接池使用的值(数据源配置参数)。请尝试发布它们。

我将使用以下内容确保废弃的连接被逐出并记录下来:

removeAbandoned = true
logAbandoned = true

我也会尝试减少以下值:

removeAbandonedTimeout

强制连接先前被踢出,以便您可以识别应用程序中负责保持最长连接的流。解决问题后,您可以重新调整它的值。

答案 1 :(得分:0)

我有类似的问题。 在我的情况下,我使用spring security与openSessionInViewFilter结合但顺序错误。 我的Spring安全代码打开了一个连接并且从未发布它,这是在OpenSessionInViewFilter之前完成的。

答案 2 :(得分:0)

你问“我有办法在任何特定时间找出活动和空闲连接的数量”

您可以扩展BasicDataSource并获取更多信息:

public class WrapperDataSource extends BasicDataSource implements Serializable {

private static final long serialVersionUID = 4139847655780946796L;
private static final Logger log = LoggerFactory.getLogger(WrapperDataSource.class);

@Override
public Connection getConnection() throws SQLException {
    if(log.isTraceEnabled()){ 
        log.trace("Number of active connections:" + super.getNumActive());
        log.trace("Number of idle connections:" + super.getNumIdle());
        log.trace("Number of max active:" + super.getMaxActive());
    }
    return super.getConnection();
}

@Override
public Connection getConnection(String username, String password) throws SQLException {
    if(log.isTraceEnabled()){ 
        log.trace("Number of active connections:" + super.getNumActive());
        log.trace("Number of idle connections:" + super.getNumIdle());
        log.trace("Number of max active:" + super.getMaxActive());
    }
    return super.getConnection(username, password);
}
}
顺便说一下BTW你得到了解决的问题,你问问题已经2年了:)?