I've seen a variety of discussions talking primarily about the question of the difference or not between the Repository and Data Mapper persistence system design patterns; but I think I have a decent understanding now - Data Mapper, as the name describes, simply maps objects in/out of a database, but Repository can include more complex querying. They're often imagined as working together, presumably in the manner of that Repository accesses the database via Data Mappers. Data Mapper, presumably, has the standard "CRUD" interface, and nothing else.
But this suggests a problem. How do you implement the query methods of the Repository? In particular, is the Repository only allowed to know about the DB through the Data Mappers? Whether or not that is the case, it seems there is a downside:
If the Repository can only know about the Database through the Data Mapper, then its fancy predicate method - say
getCarsByEngineType
- will have to loop through every database key, call the Mapper'sretrieve
, then check if theCar
object has the right engine type, and add it to the list returned to the caller. The problem is, that this seems like an awfully expensive way to do it performance-wise, since we have to pull up a whole bunch of irrelevant data (namely, every part of theCar
objects that are not the fields we want to examine), not to mention the computational (CPU) cost that may be involved in the object construction.If the Repository can know about the DB beside the Data Mapper, then that leaves open a question as to just how it should do so. The naive way, of course, is to directly embed low-level DB query code (e.g. SQL) into the Repository. The problem there is that that now makes the Repository as dependent on the DB as the Data Mapper, which "feels wrong". The alternative is some other abstraction has to be injected into Repository along with the Data Mapper. Or else, add more logic to Data Mapper, but then we get into eroding the careful distinction between the two. But I am hard-pressed to find this discussed, even though it seems like it should be something everyone would know!
Hence, my question is, can the Repository and Data Mapper pattern be combined without either of these seeming issues? If so, how - i.e. what is the "missing piece"?