jdbc:Could not open Hibernate Session for transaction

头天在公司还没有问题,第二天来就报这个错误

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的超时时间

[sql] view plain copy
  1. show global variables like 'wait_timeout';  

其默认值为8小时,超过这个时间,mysql会自动断开该连接。

有两种方法可以修改该值

1、命令修改

[sql] view plain copy
  1. set global wait_timeout=2147483;  
2、修改my.cnf文件
[plain] view plain copy
  1. [mysqld]   
  2. wait_timeout=2147483  
然后重启mysql



后来发现Hibernate的内置连接池性能是非常的差,还不如直接用第三方的c3p0,改用C3P0连接池,这

个连接池会自动 处理数据库连接被关闭的情况。要使用C3P0很简单,先从Hibernate里把c3p0-0.9.1.jar复

制到项目的lib目录中,再在 hibernate.properties里去掉hibernate.c3p0开头的那些属性的注释(使用缺

省值或自己需要的数值),这样 Hibernate就会自动使用C3P0代替内置的连接池了。到目前为止前面的问题

没有再出现过。 
具体在hibernate.cfg.xml中配置如下

 

Xml代码  收藏代码
  1. <span style="font-size: medium;"><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
  2.         <!--连接池的最小连接数-->   
  3.         <property name="hibernate.c3p0.min_size">5</property>  
  4.         <!--最大连接数-->   
  5.         <property name="hibernate.c3p0.max_size">30</property>  
  6.         <!--连接超时时间-->  
  7.         <property name="hibernate.c3p0.timeout">1800</property>  
  8.         <!--statemnets缓存大小-->   
  9.         <property name="hibernate.c3p0.max_statements">100</property>  
  10.         <!--每隔多少秒检测连接是否可正常使用  -->   
  11.         <property name="hibernate.c3p0.idle_test_period">121</property>  
  12.         <!--当池中的连接耗尽的时候,一次性增加的连接数量,默认为3-->   
  13.         <property name="hibernate.c3p0.acquire_increment">1</property>  
  14.         <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&amp;characterEncoding=utf-8&amp;autoReconnect=true



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章