頭天在公司還沒有問題,第二天來就報這個錯誤
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