Data Access Abstraction: The Repository Pattern

The **Repository Pattern** mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. It encapsulates the set of objects persisted in the data store and the operations performed over them, providing a more object-oriented view of the persistence layer.

I. The Collection Analogy

A Repository should feel like a `List` or `Set` of entities. You shouldn't see `save()`, but rather `add()`. You shouldn't see `update()`, because the repository manages the lifecycle of the objects it has returned.

II. Enforcing Aggregate Boundaries

In [Domain-Driven Design](DomainDrivenDesign), repositories are created only for **Aggregate Roots**.

* **Correct:** `PageRepository` (Page is a root).

* **Incorrect:** `RevisionRepository` (Revision is part of the Page aggregate; it should be accessed via `page.getRevisions()`).

III. Concrete Example: Optimized JDBC Repository

Sometimes an ORM (like JPA) generates inefficient SQL for complex domain queries. A Repository allows you to drop down to custom JDBC while keeping the domain layer clean.

```java

public class JdbcWikiPageRepository implements PageRepository {

private final JdbcTemplate jdbc;

@Override

public List<WikiPage> findRecent(int limit) {

// Hand-tuned SQL for performance

String sql = "SELECT p.* FROM pages p JOIN revisions r ON p.id = r.page_id " +

"WHERE r.date > NOW() - INTERVAL '7 days' LIMIT ?";

return jdbc.query(sql, pageRowMapper, limit);

}

}

```

IV. Technical Integrity: Repository vs. DAO

| Feature | Data Access Object (DAO) | Repository |

| :--- | :--- | :--- |

| **Focus** | Table-centric (CRUD for a table) | Domain-centric (Collection of Entities) |

| **Language** | Persistence (SQL, ResultSets) | Domain (Entities, Specifications) |

| **Mapping** | Close to the DB schema | Translates to/from Domain Model |

V. Strategic Guidelines

1. **Don't Over-Abstract:** If your repository is just a 1:1 wrapper for `JpaRepository<User, String>`, you are adding ceremony without value. Use the framework directly until you need custom logic.

2. **Specifications for Queries:** Instead of adding `findByXAndYAndZ` methods, use the [Specification Pattern](SpecificationPattern) to keep the repository interface lean and composable.

3. **No Business Logic:** Repositories are for storage and retrieval only. They should never contain business rules or validation logic; that belongs in the Aggregate Root or a Domain Service.

---

**See Also:**

- [Domain Driven Design](DomainDrivenDesign) — Aggregates and Entities.

- [Specification Pattern](SpecificationPattern) — Composable query predicates.

- [JPA and Hibernate](JpaAndHibernatePatterns) — Common implementation technology.