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

Spring 聲明式事務管理深度實踐:XML 配置與註解驅動對比

     編輯:Java 綜合教學

事務管理兩大範式

  • 程式化事務:在業務代碼中顯式控制 commit()/rollback(),靈活但侵入性強、樣板代碼多。
  • 聲明式事務:透過 AOP 將事務邏輯與業務邏輯分離,僅需配置或註解,推薦生產使用。

方案一:純 XML 配置(AOP 命名空間)

<!-- 1. 事務管理器(Hibernate 5 範例) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
</bean>

<!-- 2. 事務屬性定義(Advice) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="add*" propagation="REQUIRED"/>
        <tx:method name="save*" propagation="REQUIRED"/>
        <tx:method name="insert*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="remove*" propagation="REQUIRED"/>
        <tx:method name="get*" propagation="REQUIRED" read-only="true"/>
        <tx:method name="find*" propagation="REQUIRED" read-only="true"/>
        <tx:method name="query*" propagation="REQUIRED" read-only="true"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<!-- 3. AOP 切面綁定 -->
<aop:config>
    <aop:pointcut id="daoPointcut" expression="execution(* com.example.dao.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="daoPointcut"/>
</aop:config>

關鍵點解析

  • tx:advice 定義事務語義(傳播行為、隔離級別、超時、唯讀)。
  • aop:pointcut 用 AspectJ 表達式精準攔截目標方法(此處為 DAO 層所有方法)。
  • aop:advisor 將 Advice 與 Pointcut 綁定,完成 AOP 織入。
  • 優點:零侵入,業務代碼完全無 Spring 依賴;缺點:XML 冗長,修改需改配置。

方案二:XML + @Transactional 註解(推薦)

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

<!-- 2. 開啟註解驅動 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

註解使用規範

@Service
@Transactional(readOnly = true)  // 類級別預設唯讀
public class UserServiceImpl implements UserService {

    @Autowired private UserDao userDao;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void register(User user) {
        userDao.insert(user);
        // 其他業務邏輯...
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public User getById(Long id) {
        return userDao.selectById(id);
    }
}

註解放置位置關鍵規則

@Transactional 必須標註在「呼叫 DAO 的那一層」(通常是 Service 層),而非 DAO 層本身。 原因:Spring AOP 預設使用 JDK 動態代理(介面代理),只有透過代理物件呼叫方法時,事務攔截器才會生效。若在 DAO 實作類上加註解,且 Service 直接注入 DAO 實作類(非介面),則事務不生效。

兩種方案對比

維度純 XMLXML + 註解
耦合度低(業務代碼零 Spring 依賴)中(引入 Spring 註解 API)
可讀性需對照 XML 與代碼代碼即文檔,直觀
維護性修改配置檔,不動代碼修改註解,重編譯部署
靈活度統一攔截規則,難以針對單一方法微調方法級精細控制
推薦場景嚴格分層、團隊規範統一、遺專案現代 Spring 應用、微服務、敏捷開發

常見坑點避雷

  1. 自呼叫失效:同一類內部方法互呼叫繞過代理,解決:AopContext.currentProxy()、拆分類、使用 AspectJ 編譯時期織入。
  2. 異常吞沒導致不回滾:預設僅回滾 RuntimeException、Error,檢查異常需顯式 rollbackFor = Exception.class。
  3. 傳播行為誤用:REQUIRES_NEW 開啟獨立事務,若外層回滾不影響內層,慎用。
  4. 資料源未配置事務管理器:多資料源場景需指定 @Transactional("txManagerOrder")。

類級別 @Transactional 範例

方法級別 @Transactional 範例

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