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

HibernateUtil 單例模式最佳實踐:SessionFactory 線程安全創建與 Session 管理

     編輯:Java 綜合教學

標準實現

package com.hkwy.util;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory SESSION_FACTORY = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Configuration 會自動讀取 classpath 下的 hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError("SessionFactory 創建失敗: " + ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return SESSION_FACTORY;
    }

    /** 獲取新 Session(線程不安全,請求級) */
    public static Session openSession() {
        return SESSION_FACTORY.openSession();
    }

    /** 獲取當前線程綁定 Session(需配置 hibernate.current_session_context_class=thread) */
    public static Session getCurrentSession() {
        return SESSION_FACTORY.getCurrentSession();
    }

    /** 關閉 SessionFactory(應用關閉時調用) */
    public static void shutdown() {
        if (SESSION_FACTORY != null) SESSION_FACTORY.close();
    }
}

關鍵點解析

  1. SessionFactory 是線程安全、重量級、應用級單例:構建過程解析映射、構建元數據、準備連接池,極其昂貴,**全局僅一個**。
  2. Session 是線程不安全、輕量級、請求級:openSession() 每次創建新 Session,**必須成對 close()**。
  3. 靜態代碼塊/字段初始化保證類加載時單次構建,避免雙檢鎖等複雜單例寫法。
  4. 異常處理:構建失敗拋 ExceptionInInitializerError,快速失敗,防止後續 NPE。
  5. getCurrentSession():配合 hibernate.current_session_context_class=thread 實現「一請求一 Session」自動綁定/清理,Spring 整合時由框架管理,無需手動調用。

  6. 使用範例

    // 手動管理事務模式(無 Spring)
    public void saveUser(User user) {
        Session session = HibernateUtil.openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();
            session.save(user);
            tx.commit();
        } catch (Exception e) {
            if (tx != null) tx.rollback();
            throw e;
        } finally {
            session.close(); // 必須關閉,歸還連接
        }
    }

    避坑指南

    • ❌ 每次 DAO 方法 new Configuration().buildSessionFactory() → 連接池耗盡、元數據重複解析、性能災難。
    • ❌ Session 靜態字段共享 → 併發數據錯亂、一級緩存污染、連接洩漏。
    • ✅ SessionFactory 單例,Session 方法局部變量。
    • ✅ 配置連接池(C3P0/HikariCP),hibernate.cfg.xml 設置 hibernate.connection.pool_size 或專用連接池屬性。
    • ✅ 生產環境關閉 hbm2ddl.auto,改用 Flyway/Liquibase 管理遷移腳本。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved