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

MVC 架構中 Service 層的真正職責:事務邊界與業務邏輯的分水嶺

     編輯:程式設計疑難解答

常見誤區:Service 只是「業務邏輯」的代名詞?

很多初學者以為 Service 層就是把 Controller 的代碼搬過來,或是單純封裝 DAO 調用。實際上,Service 層的核心價值在於「事務管理」。

什麼是「一條業務」?

「一條業務」= 一個原子性的業務操作單元,要么全成功,要么全失敗回滾。例如:

  • 用戶註冊:寫入用戶表 + 寫入賬戶表 + 發送歡迎郵件(若郵件失敗,用戶/賬戶需回滾)。
  • 下單:扣庫存 + 建訂單 + 扣優惠券 + 記流水(任一步失敗,全部回滾)。
  • 轉賬:扣付款方 + 加收款方 + 記流水(雙向資金變動必須一致)。

而「登錄」通常不涉及寫入數據庫(僅查詢驗證),不屬於需事務保護的「業務」,可直接在 Controller 或單獨的 QueryService 中處理。

Service 層的鐵律

  1. 所有增刪改(CUD)操作必須在 Service 方法中,並加 @Transactional。
  2. 查詢(R)可在 Controller/Service/Repository 任意層,視項目規範而定,但不加事務註解(或 readOnly=true)。
  3. Service 方法粒度 = 事務邊界:一個公共方法對應一個事務。私有方法不開啟新事務(默認傳播行為)。
  4. 異常回滾:默認拋出 RuntimeException/Error 回滾,檢查型異常需 rollbackFor 指定。

代碼示範

@Service
public class OrderService {
    @Autowired OrderMapper orderMapper;
    @Autowired StockMapper stockMapper;

    @Transactional(rollbackFor = Exception.class) // 明確所有異常回滾
    public void placeOrder(OrderDTO dto) {
        // 1. 扣庫存
        stockMapper.deduct(dto.getSkuId(), dto.getCount());
        // 2. 建訂單
        orderMapper.insert(dto.toOrder());
        // 3. 扣優惠券
        couponMapper.use(dto.getCouponId());
        // 任一步拋異常,前兩步自動回滾
    }
}

Controller 的角色

  • 接收參數、校驗格式(JSR303)。
  • 調用 Service,捕獲業務異常轉為友好提示。
  • 返回視圖/JSON,不包含任何數據庫操作邏輯。

總結

Service 層不是「業務邏輯的垃圾桶」,而是事務邊界的守門人。劃分 Service 方法時,問自己:「這組操作能否部分成功?」若不能,則合併為一個事務方法。

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