Data Mapper
Data Mapper transfers data between domain objects and the database through a separate layer, keeping the model free of persistence code. It supports rich, testable domain models at the cost of complex object-relational mapping.
Data Mapper is a data-access pattern that transfers data between domain objects and a database while keeping the two completely independent of each other and of the mapper itself. Domain objects contain no code about how they are saved or loaded; they are pure model classes. A separate mapper layer knows both the object structure and the database schema and translates between them, allowing each to evolve on its own.
How It Works
For each aggregate or entity, a mapper class provides methods to load objects from the database and to save changes back. On load, it reads rows, instantiates domain objects, and populates their fields, handling relationships, inheritance, and value objects. On save, it reverses the process, generating the right inserts and updates. Because the domain object never references the mapper, the mapping logic, including the impedance mismatch between an object graph and relational tables, is fully isolated.
Object-relational mappers like Hibernate and Entity Framework are sophisticated implementations of Data Mapper, often combined with a Unit of Work for change tracking and a Repository for a domain-friendly interface.
When to Use It
Use Data Mapper when you have a rich domain model whose structure differs significantly from the database schema, when you want domain logic to be testable without a database, or when the persistence mechanism may change. It suits complex business applications, domain-driven design, and systems where keeping the model clean of infrastructure concerns is a priority.
Trade-offs
The pattern is more complex than alternatives: you maintain mapping code or configuration in addition to the domain and schema. The object-relational impedance mismatch makes mapping inheritance, collections, and lazy loading genuinely hard, and naive mappers can trigger inefficient query patterns such as the N+1 problem. For simple applications whose objects mirror their tables, the lighter Active Record pattern is often enough and less work.
Related Patterns
Active Record is the main alternative, fusing data access into the domain object instead of separating it, which is simpler but couples model to schema. Repository layers a collection-like domain interface over a mapper. Unit of Work coordinates the writes a mapper performs within a transaction.
Example
A Customer domain class holds name, address value objects, and a list of orders, with no persistence code. A CustomerMapper loads a customer by joining the relevant tables and reconstructs the object graph, and saves by writing the customer and its orders back. The domain model can be unit-tested entirely in memory, and a schema change touches only the mapper.