最近在做一个项目,测试的时候是没有问题的,但是放到服务器上以后,第二天就会出现下面的异常。重启Tomcat服务器后就正常了,但是下一天还是会出现同样的异常..... 我就查了一些资料最终把问题给解决了!
org.hibernate.exception.JDBCConnectionException: could not execute query
org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:74)
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
org.hibernate.loader.Loader.doList(Loader.java:2148)
org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029)
org.hibernate.loader.Loader.list(Loader.java:2024)
org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:375)
org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:308)
org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:153)
org.hibernate.impl.SessionImpl.list(SessionImpl.java:1106)
org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
com.schoolstar.dao.impl.UserDaoImpl.findAllverifyOkUsers(UserDaoImpl.java:53)
com.schoolstar.services.impl.UserServiceImpl.findAllverifyOkUsers
.....................................................
** BEGIN NESTED EXCEPTION **
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
MESSAGE: The last packet successfully received from the server was41577 milliseconds ago.The last packet sent successfully to the server was 41577 milliseconds ago, which 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.
.................
STACKTRACE:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was41577 milliseconds ago.The last packet sent successfully to the server was 41577 milliseconds ago, which 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.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
...................
Caused by: java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3251)
我找了一下原因发现是:MySQL对所有连接的有效时间默认为28800秒,正好8小时,也就是说,如果一个连接8小时没有请求和操作,就会自动断开(即使修改了MySQL连接的有效时间,问题在这里无法得到根本解决);而Hibernate中并没有配置连接池,使用的是它自带的也就是DriverManagerConnectionProvider。而这个连接池不支持在分配一个连接时,测试其有效与否的功能(不过根据异常提示可以再Jdbc连接的URL中加入属性'autoReconnect=true'),因此这个连接池并不知道它所管理的连接中是否有被MySQL断开的。如果一个程序要使用数据库连接,而Hibernte的连接池分配一个已经被MySQL断开了的给程序使用,那么便会出现错误。
我查了一下Hibernate支持如下的连接池:
1.DriverManagerConnectionProvider:代表由Hibernate提供的默认的数据库连接池 2.C3P0ConnectionProvider:代表C3P0连接池
3.ProxoolConnectionProvider:代表Proxool连接池
4.DBCPConnectionProvider:代表DBCP连接池
其他3个数据连接池都提供检查连接是否有效的功能,正好是可以解决上面的问题。这里我采用C3P0连接池(Hibernate文档中推荐的),首先导入C3P0的Jar包(c3p0.jar),再在Hibernate配置中加入:
<property name="hibernate.connection.provider_class">
org.hibernate.connection.C3P0ConnectionProvider
property>
<property name="c3p0.acquire_increment">1property>
<property name="c3p0.idle_test_period">300property>
<property name="c3p0.max_size">20property>
<property name="c3p0.max_statements">100property>
<property name="c3p0.min_size">5property>
<property name="c3p0.timeout">90property>
<property name="c3p0.preferredTestQuery ">select 1 from user where id=1property>
<property name="c3p0.idleConnectionTestPeriod ">18000property>
<property name="c3p0.maxIdleTime">25000property>
<property name="c3p0.testConnectionOnCheckout">trueproperty>
Ok问题解决,
另附使用Proxool连接池解决此问题的方法:
下面就看看如何配置Proxool:
1、Hibernate配置文件:
…
其中各属性含义如下:
hibernate.connection.provider_class:指明使用Proxool连接池
hibernate.proxool.xml:指明Proxool配置文件所在位置,这里与Hibernate的配置文件在同一目录下
hibernate.proxool.pool_alias:指明要使用的proxool.xml中定义的proxool别名。
2、Proxool配置文件(proxool.xml):
Anything outside the “proxool” tag is ignored. ?>
jdbc:mysql://localhost/yourDatebase?useUnicode=true&characterEncoding=UTF-8
3、下载和安装Proxool的包文件
下载地址:http://proxool.sourceforge.net/download.html
下载后并解压后,将其中lib文件夹下的jar文件拷贝到你站点的WEB-INF/lib下
自此,Proxool配置成功。重新启动Tomcat,再次做上述测试,问题解决。
此外,C3P0或DHCP,还可以参考以下资料:
http://blog.csdn.net/lip8654/archive/2008/02/26/2121387.aspx
http://azi.iteye.com/blog/182146
http://fishyych.iteye.com/blog/90793