Sql Server连接已关闭

时间:2016-02-23 23:05:43

标签: java sql-server spring hibernate sql-server-2012

我有一个连接到SQL Server 2012下的数据库的java spring应用程序。 这是我正在使用的属性和数据源:

-datasource.initialSize=34

-datasource.minIdle=89

-datasource.maxIdle=233

-datasource.maxActive=377

-datasource.maxWait=50000

-datasource.abandonWhenPercentageFull=50

-datasource.jmxEnabled=true

-datasource.removeAbandoned=true

-datasource.removeAbandonedTimeout=120

-datasource.logAbandoned=true

-datasource.testOnBorrow=true

-datasource.timeBetweenEvictionRunsMillis=60000

-datasource.minEvictableIdleTimeMillis=80000

-datasource.validationInterval=40000

和spring管理的数据源:

 <bean id="myDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close" 

            p:driverClassName="${datasource.driverClass}"
            p:url="${datasource.url}"
            p:username="${datasource.user}"
            p:password="${datasource.pass}" 
            p:maxWait="${datasource.maxWait}" 
            p:minIdle="${datasource.minIdle}"
            p:maxIdle="${datasource.maxIdle}"
            p:maxActive="${datasource.maxActive}"

            p:jmxEnabled="${datasource.jmxEnabled}"
            p:removeAbandoned="${datasource.removeAbandoned}"
            p:removeAbandonedTimeout="${datasource.removeAbandonedTimeout}"
            p:logAbandoned="${datasource.logAbandoned}"
            p:testOnBorrow="${datasource.testOnBorrow}"
                 p:timeBetweenEvictionRunsMillis="${datasource.timeBetweenEvictionRunsMillis}"
            p:minEvictableIdleTimeMillis="${datasource.minEvictableIdleTimeMillis}"
            p:validationInterval="${datasource.validationInterval}"
            p:abandonWhenPercentageFull="${datasource.abandonWhenPercentageFull}"
            p:validationQuery="SELECT 1" 
            p:jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;org.apache.tomcat.jdbc.pool.interceptor.ConnectionState"
        />

我有一个发送大量JMS消息的进程。我在不同时间收到相同的错误消息,说我的JMS侦听器中的连接已关闭。知道为什么它会关闭连接吗?

org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Unable to commit against JDBC Connection
    at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:585)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at com.spectrags.fundhive.interceptor.PerfInterceptor.invoke(PerfInterceptor.java:34)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    at com.spectrags.fundhive.business.api.messaging.WorkflowJmsListener$$EnhancerBySpringCGLIB$$704b2c20.onMessage(<generated>)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:746)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:684)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:651)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:315)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:253)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1150)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1142)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1039)
    at java.lang.Thread.run(Unknown Source) Caused by: org.hibernate.TransactionException: Unable to commit against JDBC Connection
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:86)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
    at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:581)
    ... 21 more
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.checkClosed(SQLServerConnection.java:388)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.commit(SQLServerConnection.java:1936)
    at sun.reflect.GeneratedMethodAccessor150.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
    at org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:152)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
    at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:70)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
    at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:70)
    at org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer.invoke(ResetAbandonedTimer.java:62)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
    at org.apache.tomcat.jdbc.pool.TrapException.invoke(TrapException.java:40)
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108)
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81)
    at com.sun.proxy.$Proxy21.commit(Unknown Source)
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.commit(AbstractLogicalConnectionImplementor.java:80)
    ... 24 more

编辑2016年2月25日:这是我已经实施的,但它仍然无法运作:

public class ConnectionJDBCInterceptor extends JdbcInterceptor {

    protected static Logger log = Logger.getLogger(ConnectionJDBCInterceptor.class.getName());

    @Override
    public void reset(final ConnectionPool pool, final PooledConnection pooledConnection) {

        try {
            if (pooledConnection.getConnection().isClosed()) {
                ConnectionJDBCInterceptor.log.info("Closed connection in the pool is being reconnected");
                pooledConnection.reconnect();
            }
        } catch (final SQLException e) {
            ConnectionJDBCInterceptor.log.error(e, "Error in JDBC Interceptor", e);
        }
    }

}

3 个答案:

答案 0 :(得分:2)

我有类似的问题。在IOException的情况下,sqlserver jdbc驱动程序将连接标记为已关闭,但池未检测到此情况。因此,连接在池中返回,但不可用。 解决这个问题的方法是为tomcatjdbc编写一个新的JDBCInterceptor。拦截器必须在调用close时,在底层连接上调用“isClosed”。如果底层连接已关闭,则拦截器必须将PooledConnection标记为已丢弃。 然后配置您的池以使用此拦截器。

答案 1 :(得分:0)

如果您不使用Tomcat JDBC池,则可以将其从项目中排除,从而解决了重新连接的问题。

对于gradle:

configurations.all {
  exclude group: 'org.apache.tomcat', module: 'tomcat-jdbc' 
}

答案 2 :(得分:0)

遇到了同样的问题,并为问题here

找到了很好的解释和解决方案

目前,由于默认设置或显式配置的空闲超时设置,您的数据库或应用程序服务器(例如JBoss)连接池管理器已使某些连接无效,同时,hibernate的内部数据库连接池管理器将这些连接作为有效连接。因此,当您的应用程序尝试重用它们时,您会收到连接关闭错误,直到重新启动应用程序服务器后,该错误才会清除。

要解决此问题,只需将休眠连接池管理委派给名为hibernate-c3p0的帮助程序库,并遵循示例配置,例如

{{1}}

这些属性在上面的链接以及here

中都有很好的解释。