首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Spring 3.2 + Hibernate 4.2.8 整合報錯:Could not open Hibernate Session for transaction 解決方案

     編輯:程式設計綜合問答

錯誤堆疊核心

org.springframework.transaction.CannotCreateTransactionException:
Could not open Hibernate Session for transaction;
nested exception is org.hibernate.exception.JDBCConnectionException: Could not open connection

根因分析

資料庫連線在閒置一段時間後被 MySQL 伺服器主動斷開 (預設 wait_timeout=8h),連線池持有的連線變成「失效連線」。後續嘗試獲取連線開啟 Session 時,JDBC 驅動拋出 Communications link failure,Hibernate 包裝為 JDBCConnectionException,Spring 再包裝為 CannotCreateTransactionException。

解決方案:連線池層面啟用「存活檢測」

C3P0 配置 (推薦)

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8"/>
    <property name="user" value="root"/>
    <property name="password" value="password"/>

    <!-- 核心存活檢測參數 -->
    <property name="preferredTestQuery" value="SELECT 1"/>        -- 高效測試查詢
    <property name="idleConnectionTestPeriod" value="300"/>       -- 每 300 秒 (5 分鐘) 檢測一次閒置連線
    <property name="testConnectionOnCheckin" value="true"/>       -- 歸還池時檢測
    <property name="testConnectionOnCheckout" value="true"/>      -- 從池取出時檢測 (效能稍低但最保險)
    <property name="maxIdleTime" value="1800"/>                   -- 閒置超過 30 分鐘銷毀,避免累積失效連線

    <!-- 池大小 -->
    <property name="minPoolSize" value="5"/>
    <property name="maxPoolSize" value="20"/>
    <property name="acquireIncrement" value="3"/>
</bean>

Druid 配置 (阿里巴巴,生產環境首選)

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>

    <!-- 核心存活檢測 -->
    <property name="validationQuery" value="SELECT 1"/>
    <property name="testOnBorrow" value="true"/>           -- 取出時檢測
    <property name="testOnReturn" value="false"/>          -- 歸還時不檢測 (效能)
    <property name="testWhileIdle" value="true"/>          -- 閒置檢測開啟
    <property name="timeBetweenEvictionRunsMillis" value="60000"/> -- 每 60 秒掃描一次
    <property name="minEvictableIdleTimeMillis" value="300000"/> -- 閒置 5 分鐘以上可被驅逐
    <property name="keepAlive" value="true"/>              -- MySQL 專用:定時 ping 保持長連線

    <!-- 池大小 -->
    <property name="initialSize" value="5"/>
    <property name="minIdle" value="5"/>
    <property name="maxActive" value="20"/>
</bean>

HikariCP 配置 (Spring Boot 2.x 預設,高效能)

<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8"/>
    <property name="username" value="root"/>
    <property name="password" value="password"/>

    <property name="connectionTestQuery" value="SELECT 1"/>
    <property name="idleTimeout" value="300000"/>        -- 5 分鐘
    <property name="maxLifetime" value="1800000"/>       -- 30 分鐘強制換新
    <property name="minimumIdle" value="5"/>
    <property name="maximumPoolSize" value="20"/>
</bean>

MySQL 伺服器端配合 (可選)

[mysqld]
wait_timeout = 28800          # 8 小時 (預設)
interactive_timeout = 28800
# 建議將 wait_timeout 設大於連線池 maxLifetime/idleTimeout,讓池端主動管理生命週期

驗證步驟

  1. 啟動應用,確認連線池初始化成功。
  2. 2. 手動殺掉資料庫端連線:KILL CONNECTION_ID(); (MySQL) 或重啟 MySQL 服務。 3. 等待 idleConnectionTestPeriod / timeBetweenEvictionRunsMillis 間隔過後。 4. 發起業務請求,觀察是否自動重連成功、無異常拋出。

總結

「Could not open Hibernate Session for transaction」本質是連線池持有失效連線。核心解法:在連線池層面配置存活檢測 (testQuery + 定期檢測 + 取出/歸還檢測),並淘汰舊版 DBCP,改用 **C3P0 / Druid / HikariCP**。Druid 在國內生產環境最成熟,HikariCP 效能最強,C3P0 配置最經典。三選一,務必正確配置上述參數,即可徹底解決閒置斷連問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved