头天在公司还没有问题,第二天来就报这个错误
09:11:37,931 ERROR DefaultDispatcherErrorHandler:42 - Exception occurred during processing request: Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionException: JDBC begin transaction failed:
org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionException: JDBC begin transaction failed:
at org.springframework.orm.hibernate5.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:541)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:427)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
at com.sunshine.service.StaffService$$EnhancerBySpringCGLIB$$df3b14d.login(<generated>)
具体解释是这样的:Mysql服务器默认的“wait_timeout”是8小时【也就是默认的值默认是28800秒】,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection,通俗的讲就是一个连接在8小时内没有活动,就会自动断开该连接。
wait timeout的值可以设定,但最多只能是2147483,不能再大了。也就是约24.85天
所以即使你MySQL通过my.ini 在
# The TCP/IP Port the MySQL Server will listen on
port=3306下面添加
# this is myown dinifition for mysql connection timeout
wait_timeout=31536000
interactive_timeout=31536000
无论超过最大限度多大的数值,只能被MySQL解析为2147483,2147483天后你的程序该出什么错还是什么错,避免不了的
具体操作:在数据库操作系统(我的是Navicat)中写查询修改语句
通过下面命令可以查看mysql的超时时间
- show global variables like 'wait_timeout';
其默认值为8小时,超过这个时间,mysql会自动断开该连接。
有两种方法可以修改该值
1、命令修改
- set global wait_timeout=2147483;
- [mysqld]
- wait_timeout=2147483
后来发现Hibernate的内置连接池性能是非常的差,还不如直接用第三方的c3p0,改用C3P0连接池,这
个连接池会自动 处理数据库连接被关闭的情况。要使用C3P0很简单,先从Hibernate里把c3p0-0.9.1.jar复
制到项目的lib目录中,再在 hibernate.properties里去掉hibernate.c3p0开头的那些属性的注释(使用缺
省值或自己需要的数值),这样 Hibernate就会自动使用C3P0代替内置的连接池了。到目前为止前面的问题
没有再出现过。
具体在hibernate.cfg.xml中配置如下
- <span style="font-size: medium;"><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
- <!--连接池的最小连接数-->
- <property name="hibernate.c3p0.min_size">5</property>
- <!--最大连接数-->
- <property name="hibernate.c3p0.max_size">30</property>
- <!--连接超时时间-->
- <property name="hibernate.c3p0.timeout">1800</property>
- <!--statemnets缓存大小-->
- <property name="hibernate.c3p0.max_statements">100</property>
- <!--每隔多少秒检测连接是否可正常使用 -->
- <property name="hibernate.c3p0.idle_test_period">121</property>
- <!--当池中的连接耗尽的时候,一次性增加的连接数量,默认为3-->
- <property name="hibernate.c3p0.acquire_increment">1</property>
- <property name="hibernate.c3p0.validate">true</property></span>
MySQL 的默认设置下,当一个连接的空闲时间超过8小时后,MySQL 就会断开该连接,而 c3p0 连接池则以为该被断开的连接依然有效。在这种情况下,如果客户端代码向 c3p0 连接池请求连接的话,连接池就会把已经失效的连接返回给客户端,客户端在使用该失效连接的时候即抛出异常。
解决方案:
①:增加 MySQL 的 wait_timeout 属性的值。修改 /etc/mysql/my.cnf 文件,在 [mysqld] 节中
# Set a connection to wait 8 hours in idle status.
wait_timeout = 86400
②:减少连接池内连接的生存周期,使之小于上一项中所设置的 wait_timeout 的值。
修改 c3p0 的配置文件,设置<property name="maxIdleTime" value="3600" />
③: 定期使用连接池内的连接,使得它们不会因为闲置超时而被 MySQL 断开。
修改 c3p0 的配置文件,设置:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="preferredTestQuery" value="'SELECT 1'"/>
<property name="idleConnectionTestPeriod" value="18000" />
<property name="testConnectionOnCheckout" value="true" />
<!-- other properties -->
</bean>
如果其他数据支持重连接可以在URL后加上:
jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=utf-8&autoReconnect=true