patterntypescriptMajor
Unit of Work Pattern: Batch Database Changes in a Single Transaction
Viewed 0 times
unit of worktransactionatomicityrepository coordinationprisma transactionbatch commit
Problem
Multiple repository calls in a single use case each open their own database connection/transaction. Either all changes should commit together or none should, but individual repositories cannot coordinate.
Solution
A Unit of Work object wraps a transaction and exposes repositories that all operate within it. Commit or rollback the entire batch at the end.
interface UnitOfWork {
users: UserRepository;
orders: OrderRepository;
commit(): Promise<void>;
rollback(): Promise<void>;
}
class PrismaUnitOfWork implements UnitOfWork {
users: UserRepository;
orders: OrderRepository;
private tx: PrismaTransaction;
constructor(prisma: PrismaClient) {
this.tx = prisma; // simplified; real impl wraps $transaction
this.users = new PrismaUserRepository(this.tx);
this.orders = new PrismaOrderRepository(this.tx);
}
async commit() { /* commit tx */ }
async rollback() { /* rollback tx */ }
}
// Use case
async function placeOrder(uow: UnitOfWork, userId: string, items: Item[]) {
const user = await uow.users.findById(userId);
const order = Order.create(user!, items);
await uow.orders.save(order);
await uow.users.save(user!.deductCredits(order.total));
await uow.commit();
}Why
Unit of Work ensures atomicity across multiple repository operations that logically belong to the same business transaction, preventing partial updates that corrupt data integrity.
Gotchas
- A Unit of Work is scoped to a single request or use case. Never share a UoW across requests.
- Prisma's
$transactioncallback pattern is a built-in Unit of Work — you may not need to implement this yourself with Prisma. - Always rollback in a
finallyblock or error handler to avoid holding database connections open.
Revisions (0)
No revisions yet.