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

HttpSession 與 Hibernate Session 徹底區別:Web 會話 vs 持久化會話

     編輯:Java 綜合教學

前言

初學者極易混淆 javax.servlet.http.HttpSession 與 org.hibernate.Session,兩者同名卻職責截然不同。本文從來源、生命周期、用途、作用域、代碼模式五個維度徹底釐清,並給出正確使用模板。

一、核心對比表

維度HttpSession (Web 會話)Hibernate Session (持久化會話)
全限定名javax.servlet.http.HttpSessionorg.hibernate.Session
核心職責標識用戶身份,跨請求保存會話狀態管理實體對象生命周期,執行 CRUD,事務邊界
創建者Servlet 容器(Tomcat/Jetty)自動創建應用代碼手動獲取 SessionFactory.openSession()
生命周期用戶無操作超時(默認 30min)自動銷毀業務邏輯開始→提交/回滾→手動關閉
作用域單用戶、跨多個請求(同一瀏覽器會話)單線程、單業務事務(通常一個 Service 方法)
存儲內容用戶 ID、權限、購物車、CSRF Token 等持久化實體、一級緩存、SQL 翻譯上下文
並發模型多線程共享(需同步或用 ConcurrentHashMap)非線程安全,嚴禁多線程共享
獲取方式request.getSession()sessionFactory.openSession() / getCurrentSession()
典型用法session.setAttribute("user", user)session.save(entity); session.createQuery(...)

二、HttpSession 詳細解析

1. 創建與獲取

// 獲取或創建(首次訪問)
HttpSession session = request.getSession(); // 等同 request.getSession(true)

// 僅獲取不創建
HttpSession session = request.getSession(false); // 可能返回 null

2. 核心 API

// 存值
session.setAttribute("userId", 1001);
session.setAttribute("permissions", permList);

// 取值
Integer userId = (Integer) session.getAttribute("userId");

// 刪除單個
session.removeAttribute("tempData");

// 銷毀整個會話(登出)
session.invalidate();

// 設置超時(秒),-1 為永不超時
session.setMaxInactiveInterval(1800); // 30 分鐘

3. 底層原理

  • 容器維護 Map,Key 為 JSESSIONID
  • Client 端 Cookie 存儲 JSESSIONID,每次請求攜帶
  • 分佈式場景需 Session 共享(Redis、Sticky Session、DB 持久化)

三、Hibernate Session 詳細解析

1. 核心定位

Hibernate Session = 工作單元 = 一級緩存 = 事務邊界 的載體

2. 標準使用模式(Open Session in View / 模式)

@Service
@Transactional // Spring 管理事務,自動綁定 Session 到線程
public class AccountService {
    
    @Autowired SessionFactory sessionFactory;
    
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        // 獲取當前事務綁定的 Session(Spring 自動管理 open/close)
        Session session = sessionFactory.getCurrentSession();
        
        Account from = session.get(Account.class, fromId);
        Account to   = session.get(Account.class, toId);
        
        from.debit(amount);
        to.credit(amount);
        
        // 無需顯式 save/update,實體在 Session 管理下自動髒檢查
        // @Transactional 提交時自動 flush → commit
    }
}

3. 手動管理模式(非 Spring 環境)

Session session = sessionFactory.openSession();
Transaction tx = null;
try {
    tx = session.beginTransaction();
    
    Account from = session.get(Account.class, 1L);
    Account to = session.get(Account.class, 2L);
    from.debit(amount); to.credit(amount);
    
    tx.commit(); // flush + commit
} catch (Exception e) {
    if (tx != null) tx.rollback();
    throw e;
} finally {
    session.close(); // 必須關閉,釋放 JDBC 連接、清理一級緩存
}

4. 關鍵特性

  • 一級緩存:同一 Session 內多次 get(id) 返回同一對象引用
  • 髒檢查:事務提交前自動檢測實體屬性變更,生成 UPDATE SQL
  • 延遲加載:關聯實體首次訪問時觸發 SQL 查詢(需 Session 開啟)
  • 非線程安全:每個線程獨享一個 Session

四、常見混淆場景澄清

場景錯誤認知正確理解
「把 Hibernate Session 放進 HttpSession」跨請求復用數據庫連接❌ 嚴禁!Session 非線程安全、連接會泄漏、實體變脫管狀態
「HttpSession 存實體對象」方便下次請求直接用⚠️ 可存 ID/DTO,不可存持久化實體(序列化失脫管、佔內存、並發衝突)
「事務跨多個 HTTP 請求」用戶向導式操作❌ 反模式。用樂觀鎖/狀態機/臨時表實現長事務業務
「Session 就是數據庫連接」一一對應Session 內部持有 Connection,但有連接池複用,Session 關閉不一定關閉物理連接

五、Spring 整合最佳實踐

// 配置類
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
    LocalSessionFactoryBean sf = new LocalSessionFactoryBean();
    sf.setDataSource(dataSource);
    sf.setPackagesToScan("com.example.entity");
    sf.setHibernateProperties(hibernateProps());
    return sf;
}

@Bean
public HibernateTransactionManager txManager(SessionFactory sf) {
    return new HibernateTransactionManager(sf);
}

// Service 只需 @Transactional
@Service
@Transactional
public class OrderService { ... }

六、總結

  • HttpSession = Web 層用戶會話容器,容器管理,存業務狀態(用戶、權限、購物車)
  • Hibernate Session = 數據層持久化工作單元,代碼管理,管實體生命周期(CRUD、緩存、事務)
  • 兩者絕不互相引用、互相存儲,分層架構的核心體現
  • Spring @Transactional 自動綁定 Session 到線程,業務代碼無感知
  • 分佈式系統中:HttpSession 用 Redis 共享,Hibernate Session 仍維持請求級別
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved