Repository Pattern 把「怎麼存資料」抽象化了。但它解決不了一個問題:

建訂單要同時更新三個地方——訂單表、庫存表、用戶積分表。如果訂單寫成功但庫存更新失敗,資料就不一致了。這三個操作必須在同一個 transaction 裡,要嘛全成功,要嘛全回滾。

OrderRepositoryInventoryRepositoryUserRepository 各自獨立——誰來協調它們的 transaction 邊界?

這是 Unit of Work Pattern 要解決的問題。


Unit of Work 的角色

Unit of Work 做兩件事:

追蹤變更:在一個業務操作(Use Case)期間,所有對 domain object 的修改都被 UoW 記錄下來,暫時不寫進 DB。

統一提交:業務操作結束時,呼叫 unitOfWork.commit(),UoW 把所有變更包在一個 transaction 裡寫入。如果任何一步失敗,整個 transaction rollback。

// 業務操作(Application Service)
async function createOrder(command: CreateOrderCommand) {
  const uow = unitOfWorkFactory.create()

  const order = new Order(...)
  const inventory = await uow.inventories.findById(command.productId)

  inventory.reserve(command.quantity)    // 只是修改記憶體裡的物件
  order.addItem(inventory, command.qty)  // 同上

  await uow.orders.save(order)           // 登記要儲存 order
  await uow.inventories.save(inventory)  // 登記要儲存 inventory

  await uow.commit()  // ← 這裡才真的寫進 DB,在同一個 transaction
}

業務邏輯不需要知道「transaction 怎麼管理」,也不需要顯式呼叫 BEGIN TRANSACTION / COMMIT——那些是 infrastructure 的細節,交給 UoW 處理。


UoW 和 Repository 的分工

Repository 負責單一 Aggregate 的存取抽象——「給我 order #123」「把這個 order 存起來」。它不知道有沒有其他操作在同一個 transaction 裡。

Unit of Work 負責一個業務操作的 transaction 邊界——它持有所有 Repository,確保它們共用同一個 DB connection / session,讓最後的 commit() 能把所有變更包在一起。

兩者的關係:UoW 管 Repository,Repository 管 Aggregate。


框架裡的 UoW

很多框架已經把 Unit of Work 內建了,只是沒有用這個名字叫它:

  • Spring @Transactional:方法加上這個 annotation,整個方法執行期間的所有 DB 操作在同一個 transaction,方法正常結束 commit,拋例外 rollback。這就是 UoW 的概念,只是用 AOP 自動化了。

  • Entity Framework (C#)DbContext 本身就是 UoW——你操作 context.Orders.Add(order),不立刻寫 DB,呼叫 context.SaveChanges() 才統一提交。

  • SQLAlchemy (Python)Session 物件是 UoW,用 session.add() 追蹤變更,session.commit() 統一寫入。

知道「Unit of Work」這個名字,是為了理解這些框架在做什麼——DbContextSession@Transactional 背後的概念是一致的。


什麼時候需要手動實作 UoW

如果你用的框架已經提供了 UoW(Spring、EF、SQLAlchemy),通常不需要自己實作——直接用框架的 session 管理就夠了。

需要手動實作的情況是:你在 Clean Architecture 或 Hexagonal Architecture 裡,要讓 Application Service 不直接依賴框架的 session 物件(因為那會讓 application 層耦合 infrastructure)。這時你定義一個 UnitOfWork 介面在 application 層,把 commit() / rollback() 的行為抽象化,infrastructure 層再提供具體的 PostgresUnitOfWork 實作,讓框架的 session 在那裡管。


上一篇 → Repository Pattern

下一篇 → Layered Architecture