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

Spring 4 + Hibernate 4 事務管理:為何未配置事務仍能保存?核心機制深度解析

     編輯:程式設計疑難解答

Spring 4.1.4 整合 Hibernate 4 時,發現未聲明 @Transactional、未配置 AOP 事務切面,直接呼叫 session.save() 竟能成功提交資料庫?本文深入剖析 Hibernate 原生事務、Spring 事務代理、CurrentSessionContext 三者交互機制。

現象重現

// 無 @Transactional、無 XML 事務配置
Session session = sessionFactory.getCurrentSession();
session.save(entity); // 竟然提交成功!

核心真相:Hibernate 自帶事務 API,Spring 只是「代理管理」

層面Hibernate 原生Spring 事務管理
APITransaction tx = session.beginTransaction(); tx.commit();@Transactional / XML <tx:advice>
邊界手動控制(程式碼侵入)聲明式、切面攔截(非侵入)
回滾手動 tx.rollback()異常自動回滾、支援嵌套
傳播行為無REQUIRED、REQUIRES_NEW 等 7 種

為何「不配置 Spring 事務」也能提交?

  1. CurrentSessionContext 綁定:sessionFactory.getCurrentSession() 依賴 hibernate.current_session_context_class 設定(如 thread、managed),從當前執行緒取得 Session。
  2. 自動提交模式:若資料庫連線池預設 autoCommit=true,且未開啟 Hibernate 事務,每條 SQL 即時提交。
  3. Session 生命週期:getCurrentSession() 在 SessionFactory 關閉或手動 close() 時自動 flush 並提交(視實作而定)。

危險性:業務完整性無保障

// 業務邏輯:轉帳(扣款 + 入帳)
public void transfer(Account from, Account to, int amount) {
    session.update(from); // 扣款成功
    // 這裡拋出異常(如網路中斷)
    session.update(to);   // 入帳失敗
    // 結果:資料不一致,扣款已提交無法回滾!
}

無 Spring 事務邊界 = 無原子性保障。多步操作若中途失敗,已執行步驟無法回滾,導致髒資料。

Spring 事務管理的核心價值

  • 原子性:業務方法內多個 DAO 操作,要么全成功,要么全回滾。
  • 一致性:異常觸發自動回滾,維護資料完整性約束。
  • 隔離性:配置隔離級別(READ_COMMITTED 等)防止髒讀/不可重複讀。
  • 傳播行為:巢狀業務呼叫時正確處理事務邊界(REQUIRED、REQUIRES_NEW、NESTED)。

正確配置範例

XML 配置

<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>

註解配置(推薦)

@Configuration
@EnableTransactionManagement
public class TxConfig { ... }

@Service
public class AccountService {
    @Transactional(rollbackFor = Exception.class)
    public void transfer(...) { ... }
}

關於 HibernateTemplate 的補充

  • Spring 3.1+ 不建議使用 HibernateTemplate,直接注入 SessionFactory 呼叫 getCurrentSession() 即可。
  • HibernateTemplate 主要解決舊版 Hibernate checked exception、Session 管理樣板碼,現代版本已無此痛點。
  • 若遇 HibernateTemplate.save() 報「事務為只讀」,檢查 @Transactional(readOnly=true) 或 XML read-only="true" 配置錯誤。

總結

「能存進去」≠「事務正確」。Hibernate 原生事務僅提供單操作提交,Spring 事務管理才是業務級原子性、一致性、隔離性的守護者。務必在 Service 層配置聲明式事務,切勿僥倖依賴自動提交行為。

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