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

Spring + Hibernate 事務管理深度解析:聲明式事務、傳播行為、隔離級別、回滾規則全覽

     編輯:Java 相關知識

背景:為什麼需要 Spring 管理 Hibernate 事務?

Hibernate 默認 autoCommit=false,手動控制事務代碼分散、易漏提交/回滾。Spring 提供 **聲明式事務管理**(AOP 切面),將事務邊界從業務代碼剝離,支持:

  • 統一配置傳播行為、隔離級別、超時、只讀、回滾規則。
  • 與 Spring 管理的 SessionFactory / EntityManagerFactory 無縫集成。
  • 支持 JDBC、Hibernate、JPA、JTA 多種資源的同一事務抽象。

XML 配置全貌(經典模式,現代項目多用 @Transactional 註解)

<!-- 1. 事務管理器:綁定 Hibernate SessionFactory -->
<bean id="transactionManager" 
      class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<!-- 2. 事務屬性定義(通過 tx:advice) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!-- 增刪改:REQUIRED,拋運行時異常回滾 -->
        <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
        <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
        <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
        <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
        <!-- 查詢:只讀、不支持事務(性能優化) -->
        <tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true"/>
        <tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true"/>
        <tx:method name="query*" propagation="NOT_SUPPORTED" read-only="true"/>
        <tx:method name="count*" propagation="NOT_SUPPORTED" read-only="true"/>
        <!-- 其餘默認 -->
        <tx:method name="*" propagation="REQUIRED" read-only="false"/>
    </tx:attributes>
</tx:advice>

<!-- 3. AOP 切面:將事務應用到 Service 層 -->
<aop:config>
    <aop:pointcut id="serviceMethods" expression="execution(* com.example.service..*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>

註解驅動模式(Spring Boot 推薦)

@Configuration
@EnableTransactionManagement
public class TxConfig {
    @Bean
    public PlatformTransactionManager txManager(SessionFactory sf) {
        return new HibernateTransactionManager(sf);
    }
}

// Service 類
@Service
@Transactional(readOnly = true) // 類級別默認只讀
public class OrderService {
    @Autowired OrderRepository repo;

    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public Order createOrder(OrderDTO dto) { ... }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void sendConfirmationEmail(Order order) { ... } // 獨立事務,不影響主訂單
}

七大傳播行為詳細對比

常量行為典型場景
REQUIRED有事務加入,無則新建(默認)90% 業務方法
SUPPORTS有事務加入,無則非事務運行查詢方法,允許在事務外調用
MANDATORY必須在現有事務中運行,否則拋異常強制要求事務上下文的核心操作
REQUIRES_NEW**掛起當前事務,新建獨立事務**日誌記錄、審計、發送通知,不回滾主業務
NOT_SUPPORTED掛起當前事務,以非事務方式運行長耗時查詢、外部 API 調用,避免長事務持有連接
NEVER不允許事務,有則拋異常嚴禁事務的工具方法
NESTED嵌套事務(保存點),外層回滾內層必回滾,內層回滾外層可繼續批量處理中單條失敗回滾,其餘繼續(需 JDBC 3.0+ 驅動支持)

隔離級別與資料庫鎖對應

Spring 常量資料庫級別髒讀不可重複讀幻讀性能
DEFAULT資料庫默認(通常 RC)視具體 DB視具體 DB視具體 DB—
READ_UNCOMMITTEDRead Uncommitted✅✅✅最高
READ_COMMITTEDRead Committed (Oracle/PG 默認)❌✅✅高
REPEATABLE_READRepeatable Read (MySQL 默認)❌❌✅ (MySQL 靠 Gap Lock 解決)中
SERIALIZABLESerializable❌❌❌最低

**建議**:大多數互聯網業務用 **READ_COMMITTED** + **樂觀鎖(@Version)** 解決併發衝突,兼顧性能與正確性。

回滾規則精準控制

  • 默認:只有未檢查異常(RuntimeException 及子類、Error)觸發回滾。
  • rollbackFor = Exception.class:所有受檢異常也回滾(常用)。
  • noRollbackFor = BusinessException.class:業務異常不回滾(如庫存不足屬業務流程,不應回滾)。
  • 編程式回滾:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。

二級緩存與事務的關係

事務邊界決定了 **Session 生命周期**(默認 OpenSessionInView 會延長到視圖渲染)。若事務在 Service 層結束,Session 關閉,二級緩存才真正生效(寫入/失效)。**將事務配置在 Service 層而非 DAO 層**,既保證業務原子性,又讓二級緩存正常工作。

避坑清單

  1. @Transactional 失效:方法非 public、類內部調用、未掃描到包、使用 final/private/static 方法。
  2. 事務未回滾:拋出受檢異常但未配置 rollbackFor、try-catch 吞掉異常未重拋。
  3. 死鎖:多表更新順序不一致,統一按「主表→從表、ID 升序」更新。
  4. 長事務:遠程調用、大批量處理放在事務外,或用 REQUIRES_NEW 縮短鎖持有時間。

總結

Spring 聲明式事務通過 AOP 將「何時開啟、何時提交、何時回滾、隔離級別、傳播行為」集中配置。掌握 **傳播行為七大類、隔離級別四大類、回滾規則精準控制**,並遵循 **「事務在 Service 層、查詢走只讀、寫操作配回滾、長任務拆獨立事務」** 原則,即可構建健壯、高性能的數據訪問層。

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