Real-world combination
Repository + Unit of Work
Repository hides persistence behind a collection-like interface; Unit of Work tracks every change made through it and commits them all in one transaction.
✗ Problem
SQL scattered through business logic
Domain code calls the database directly. It's coupled to the DB, impossible to unit-test, and if the process dies mid-way, some writes land and others don't.
function placeOrder(order) {
db.query('UPDATE stock SET qty=qty-1 WHERE id=?', [order.itemId]);
// crash here → stock decremented, order row never written
db.query('INSERT INTO orders ...', [order]);
}
Business logic knows table names and SQL syntax — swap the DB or write a
unit test and everything breaks. And nothing wraps the two writes in one transaction.
✓ The combination
→
→
→
Collection-like interface + one transaction
A Repository looks like an in-memory collection
(findById, add, remove) hiding the DB behind it. A
Unit of Work tracks everything changed through repositories in this session
and commits — or rolls back — as one transaction.
interface UserRepository {
findById(id);
add(user);
remove(user);
}
// domain only knows the interface (DIP):
userRepo.add(newUser);
userRepo.remove(oldUser);
uow.commit(); // all-or-nothing
Domain
business logic
Repository
interface
UnitOfWork
tracks changes
DB
1 transaction
✓ See it live
Add, edit, delete — then commit or rollback
Buttons act through the repository. Every change is tracked as a pending change — nothing touches the database until you commit.
Repository (working view)
Database (committed)
Unit of Work — pending changes
0 pending changes
✓ Takeaway
Why the combination earns its keep
- Swap the DB / test in memory: the domain only knows the repository interface — give it a fake for unit tests, a real one in production.
- One transaction per business operation: the Unit of Work makes multi-entity writes atomic — commit everything, or nothing.
- Persistence-ignorant domain: business logic never sees SQL, table names, or ORM sessions.
- This is how ORMs work under the hood: EF Core's
DbContextand Hibernate'sSessionare both Unit of Work + Repository. - Caution: keep repositories thin — no business rules inside, or they turn into a second domain layer.
🎯 Combines: Repository + Unit of Work behind an interface — pure Dependency Inversion + SRP (domain vs persistence).
Back to all topics →