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

事務策略:客戶端編排模式——實現基於客戶端的可靠事務協調

     編輯:Java 相關知識

當應用程序的表示層需要協調多個 API 層方法調用以完成單個邏輯工作單元(LUW)時,客戶端編排事務策略應運而生。本文詳細闡述該策略的架構、實現規則、適用場景與限制,並提供基於 EJB 3.0 的完整代碼示例。

適用場景:細粒度 API 與 Chatty 應用

若 API 層設計為細粒度(chatty),客戶端需發起多次調用才能完成一個業務單元,且難以重構為粗粒度聚合 API,則客戶端編排策略是正確選擇。此策略將事務邊界前移至客戶端層,由客戶端控制事務的開始、提交與回滾。

架構分層與事務邏輯分佈

架構層次與事務邏輯分佈圖

  • 客戶端層:唯一事務擁有者,負責程序化事務管理(begin/commit/rollback)。
  • API 層:聲明式事務,使用 MANDATORY 傳播屬性,要求調用者提供事務上下文,不包含回滾邏輯。
  • 業務層/持久層:零事務邏輯,無註解、無程序化代碼。

核心規則與特性

  1. 僅客戶端層與 API 層包含事務邏輯。
  2. 客戶端層方法為唯一事務擁有者,負責提交/回滾。
  3. 客戶端層通常需程序化事務(JTA UserTransaction),除非由 Spring 容器管理。
  4. API 層必須使用聲明式事務,容器管理事務上下文傳播。
  5. API 層所有公共寫方法標記 MANDATORY,拒絕無事務上下文的調用。
  6. API 層寫方法不包含任何回滾邏輯,遵循「只有事務擁有者才能回滾」的黃金法則。
  7. API 層讀方法默認 SUPPORTS,若在事務中調用則加入事務,否則無事務運行。
  8. 客戶端與 API 層通信協議必須支持事務上下文傳播(如 RMI-IIOP),不支持 HTTP、JMS、Web Service 客戶端。

實現示例:EJB 3.0 程序化事務

讀操作:客戶端無事務,API 層 SUPPORTS

// 客戶端層
public void getTrade() {
    InitialContext ctx = new InitialContext();
    TradingService service = (TradingService) ctx.lookup("TradingServiceImpl/remote");
    TradeData trade = service.getTrade(11); // 無事務邏輯
}

// API 層
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public TradeData getTrade(long tradeId) {
    return em.find(TradeData.class, tradeId);
}

寫操作:客戶端程序化事務,API 層 MANDATORY

// 客戶端層 - 事務擁有者
public void placeTrade() {
    UserTransaction txn = null;
    try {
        InitialContext ctx = new InitialContext();
        TradingService service = (TradingService) ctx.lookup("TradingServiceImpl/remote");
        TradeData trade = new TradeData();
        // 設置交易數據...
        
        txn = (UserTransaction) ctx.lookup("UserTransaction");
        txn.begin();                    // 1. 開始事務
        service.insertTrade(trade);     // 2. 調用 API
        service.updateAcct(trade);
        txn.commit();                   // 3. 提交事務
    } catch (Exception e) {
        if (txn != null) txn.rollback(); // 4. 異常回滾
        throw e;
    }
}

// API 層 - 無回滾邏輯,強制要求事務上下文
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public TradeData insertTrade(TradeData trade) {
    trade.setStage("PLACED");
    em.persist(trade);
    return trade;
}

@TransactionAttribute(TransactionAttributeType.MANDATORY)
public void updateAcct(TradeData trade) {
    AcctData acct = em.find(AcctData.class, trade.getAcctId());
    // 更新餘額邏輯...
}

限制與約束

  • 協議限制:客戶端與 API 層間必須支持事務傳播協議(RMI-IIOP),不可用於 Web Service、JMS、HTTP 客戶端。
  • 不可漸進式引入:API 層使用 MANDATORY,若客戶端未啟動事務直接調用將拋異常;混合使用 API 層策略會導致數據不一致。
  • 開發複雜度:客戶端開發者需掌握 JTA 程序化事務 API,增加「程序員錯誤」風險。

替代方案:代理 API 層

若必須支持非事務客戶端,可引入「代理 API 層」:該層使用 API 層策略(單一調用、REQUIRED),內部調用客戶端編排策略的 API 層。代理層成為事務擁有者,屏蔽底層複雜性。

總結

客戶端編排策略適用於細粒度 API、需多調用完成 LUW 的場景,但對架構施加較強限制。選型前需權衡:重構為粗粒度 API(使用 API 層策略) vs 接受協議限制與開發複雜度。切勿嘗試在同一應用混合多種策略。

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