Hibernate Cannot release connection (转)

问题:
系统采用Spring MVC 2.5 + Spring 2.5 + Hibernate 3.2架构,其中数据源连接池采用的是Apache commons DBCP。问题是这样的,系统运行一段时间后(大致每隔8小时),访问系统会出现如下错误,再次访问恢复正常。

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: Cannot release connection
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:
583 )
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:
501
)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:
617
)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:
717
)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:
290
)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:
206
)

Caused by: org.hibernate.exception.GenericJDBCException: Cannot release 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.closeConnection(ConnectionManager.java:
449
)
at org.hibernate.jdbc.ConnectionManager.cleanup(ConnectionManager.java:
379
)
at org.hibernate.jdbc.ConnectionManager.manualDisconnect(ConnectionManager.java:
333
)
at org.hibernate.impl.SessionImpl.disconnect(SessionImpl.java:
375
)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCleanupAfterCompletion(HibernateTransactionManager.java:
744
)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:
989
)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:
855
)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:
800
)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:
339
)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:
110
)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:
171
)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:
89
)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:
171
)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:
635)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39 )
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25
)
at java.lang.reflect.Method.invoke(Method.java:
585
)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:
421
)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:
136
)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:
326
)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:
313
)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:
875
)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:
807
)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:
571
)
36
more
Caused by: java.sql.SQLException: Already closed.
at org.apache.commons.dbcp.PoolableConnection.close(PoolableConnection.java:
77
)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.close(PoolingDataSource.java:
180
)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.closeConnection(LocalDataSourceConnectionProvider.java:
96
)
at org.hibernate.jdbc.ConnectionManager.closeConnection(ConnectionManager.java:
445
)
62
more



解决:
造成Cannot release connection的原因有很多,要具体问题具体分析。从异常分析,造成这个异常 org.hibernate.exception.GenericJDBCException: Cannot release connection 归根结底是Caused by: java.sql.SQLException: Already closed.
即连接已关闭。所以解决的办法就要从DBCP的参数配置入手,见下面的参数配置properties文件。

#### :: Apache DBCP :: ####
jdbc.driverClassName
=
oracle.jdbc.driver.OracleDriver
jdbc.url
=jdbc:oracle:thin:@10.165.153.9:1521
:PRDC
jdbc.username=
guser
jdbc.password
=guser

#初始化连接
jdbc.initialSize
=0
#连接池的最大活动个数
jdbc.maxActive
=20
#没有人用连接的时候,最大闲置的连接个数。
jdbc.maxIdle
=100
#没有人用连接的时候,最小闲置的连接个数。
jdbc.minIdle
=0
#超时等待时间以毫秒为单位
jdbc.maxWait
=10000
#是否自动回收超时连接
jdbc.removeAbandoned
=true
#设置被遗弃的连接的超时的时间(以秒数为单位),即当一个连接被遗弃的时间超过设置的时间,则它会自动转换成可利用的连接。默认的超时时间是300秒。
jdbc.removeAbandonedTimeout
=60
#是否在自动回收超时连接的时候打印连接的超时错误
jdbc.logAbandoned
=true
#给出一条简单的sql语句进行验证
jdbc.validationQuery=select 1 from dual
#在取出连接时进行有效验证
jdbc.testOnBorrow=true


其中标红的两个参数的作用是对池化连接进行验证,This will ensure that DBCP only hands out good connections to Hibernate. 故加上这两个参数后,这个异常就不会再出现了。在Spring中指定数据源如下:

<!-- 數據源定義 使用Apache DBCP連接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
<property name="maxIdle" value="${jdbc.maxIdle}"/>
<property name="maxWait" value="${jdbc.maxWait}"/>
<property name="removeAbandoned" value="${jdbc.removeAbandoned}"/>
<property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/>
<property name="logAbandoned" value="${jdbc.logAbandoned}"/>
<property name="validationQuery" value="${jdbc.validationQuery}"/>
<property name="testOnBorrow" value="${jdbc.testOnBorrow}"/>
</bean>


问题解决了。

另附

DBCP参数详细说明(部分参考了
http://justin-ray.javaeye.com/blog/413591 ):

在配置时,大部分参数一目了然,不再赘述,有不清楚的话,可以参考下面的详细说明。主要难以理解的参数主要有:removeAbandoned 、logAbandoned、removeAbandonedTimeout、maxWait这四个参数,设置了rmoveAbandoned=true那么在getNumActive()快要到getMaxActive()的时候,系统会进行无效的Connection的回收,回收的Connection为removeAbandonedTimeout(默认300秒)中设置的秒数后没有使用的Connection,激活回收机制大致为getNumActive()=getMaxActive()-3。logAbandoned=true的话,将会在回收事件后,在log中打印出回收Connection的错误信息,包括在哪个地方用了Connection却忘记关闭了,在调试的时候很有用。在这里个人建议maxWait的时间不要设得太长,maxWait如果设置太长那么客户端会等待很久才激发回收事件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值