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.
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.
In Domain-Driven Design, repositories are created only for Aggregate Roots.
PageRepository (Page is a root).RevisionRepository (Revision is part of the Page aggregate; it should be accessed via page.getRevisions()).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.
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);
}
}
| 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 |
JpaRepository<User, String>, you are adding ceremony without value. Use the framework directly until you need custom logic.findByXAndYAndZ methods, use the Specification Pattern to keep the repository interface lean and composable.See Also: