0

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:

  1. 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's retrieve, then check if the Car 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 the Car 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.

  2. 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"?

1 Answer 1

1

Stack Overflow has some good answers to this already that I'll shamelessly quote from:

In short: the 'DataMapper' deals with single objects, the 'Repository' deals with collections of objects and expands upon the functionality provided by the 'DataMapper'.

Stack Overflow - How is the Data Mapper pattern different from the Repository Pattern?

So there's a hint that they can work together. Here's a responsibility break down:

  • The business logic deals with a Repository when it wants to read or persist objects, and doesn't care how that is implemented.
  • The Repository deals with a DataMapper when it wants to read/write an object in a particular persistence medium.
  • For querying, the Repository relies on a schema provided by the DataMapper (e.g. the jobTitle value is found in the JobTitle column in the PersonTable table) but not on any implementation of a mapper.
  • For DB persistence, the DataMapper relies on a DB layer, that shield it from the Oracle/Sybase/MSSQL/OtherProvider details. Stack Overflow - What exactly is the difference between a data mapper and a repository?

As for your "missing piece" what hasn't been mentioned is how business logic queries the repository. This can be done in many different ways, but generally is not through SQL. The previous answer offered some example code:

Person johnDoe = personRepository.get(p=> p.name == "John Doe");
johnDoe.jobTitle = "IT Specialist";
personRepository.update(johnDoe);

Most notably this is not SQL. But it is something. "something that translates queries from the functional description (p=> p.name == "John Doe") to something that the persistence layer understands."

Something has to do that. You don't get it for free.

The big advantage here is SQL has to be all things to all people. But the repository API can be tailored to your specific business needs.

So the query progression can go from

  • Business logic's functional description that the
  • Repository understands and relies on a schema provided by the
  • DataMapper to retrieve the object from the persistence media

And of course caching can short circuit this.

As for performance, try it and see. This design is about keeping unneeded knowledge from spreading though the code and locking you down. It's work. No joke. Do it if that gets you something you care about.

8
  • Yes, and I actually read all that before, which is why I posted this question. The trick is that if DataMapper only has simple CRUD methods, how does Repository implement that ".get" method? As I said, the only ways I can think of is to dredge up everything, which has a potentially large performance hit, or else put additional logic in the mapper, which kind of defeats the purpose, or else Repository has to directly know about the DB, which I'm not sure if is correct for the "knowledge contract" it is supposed to fulfill. Commented Jun 28, 2023 at 15:02
  • @The_Sympathizer the fundamental shift that is hard to make if you've been using 'animic' CRUD designs is to let the business logic drive the design. Not the data. It's hard to pretend the DB doesn't exist if you think of it as central. But that's what this design is supposed to let you do. Commented Jun 28, 2023 at 15:07
  • so does that mean it's okay to put direct DB access code into the Repository, or that it's okay to load up Data Mapper with sophisticated querying capability, which makes it different from Repository ... how? Commented Jun 28, 2023 at 15:10
  • Also I'm not sure what you mean by "anemic CRUD design"; I thought the Data Mapper is supposed to be that, while Repository is supposed to be the thing that isn't "anemic"; otherwise, it seems there's no difference between the two and they can be collapsed into one. Commented Jun 28, 2023 at 15:11
  • 1
    Short of taking advantage of caching, yes. Commented Jun 28, 2023 at 15:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.