How do I use DataMapper Pattern? I can use it as a glorified Database Access Object, aka TableGateway (loading a single class from a single database table), or I can use it more to drive business concerns (i.e. load complex objects from many DB tables). Or mix both?


Suppose that in my business application I have a Product and a Motor entities. Sometimes I need just one and sometimes just the other. But sometimes I need a structure where a motor belongs to a product. (Product owns the Motor), and I need to load both, and I can create and use a single function of my DataMapper to do that.

Business-Oriented Naming/Structure

$products = new ProductDataMapper();

//This is the business-relevant construct, loading a complex object
$product = $products->getProductWithMotor(1, 2);//ids

echo $product->getName();  //"Product with id 1"
echo $product->getMotor()->getName();  //"Motor with id 2"

TableGateway Naming/Structure

$products = new ProductDataMapper();
//just loading an object by id, no specific business meaning
$product = $products->findById(1);

$motors = new MotorDataMapper();
//just loading an object by id
$motor = $motors->getMotor(2);

//business-relevant line (Product owns the Motor)
//that was hidden away inside the getProductWithMotor above, 
//now inside some business layer

echo $product->getName();  //"Product with id 1"
echo $product->getMotor()->getName();  //"Motor with id 2"


My question deals with "What was/is the intent of use of DataMapper pattern?"

Is there intent to use as a business layer (namely load business-relevant objects with DataMapper functions creating complex business-relevant objects), or is it purely intended to do simple Create/Update/Delete/Insert functions and is to disconnect itself from creating business-relevant-objects, leaving that to some business functionality layer?


Since a data mapper should have a single responsibility, it should only map the results of the query to an object or object(s) and return that back to the caller.

In your case we have:

  • Product
  • Motor

So, I think one would definately have mappers for those objects defined.

I beleive your choices for mapping product and motors are:

  1. Composition. Products, can have a list or array or motors, so it could be handled via composition. You could return back a list of motors back and then simply add those motors to the product outside the mapper.
  2. Another object called ProductMotor. The mapper maps to an object called ProductMotor and returns back an object of that type.

Either option could be acceptable depending on system usage and layout.

Based on your comments below a query with a join could return the motor and product information on one data record, some psuedo code:

Public Product MapProduct(IRecord record)
    var product = new Product();
    product.Name = record["name"].ToString();
    //And so forth...
    product.Motor = MapMotor(record);
    return product;

Public Motor MapMotor(IRecord record)
    var motor= new Motor();
    motor.Name = record["name"].ToString();
    //And so forth...
    return motor;
  • thank you. I understand #2. But for #1, can you expand on what you mean? In my case a single product cannot have many motors, but only can have one (or none). But I routinely list many products (each coupled with a Motor) Do you mean just doing something like I did in my code (Having different mappers for each class?) – Dennis Jul 2 '15 at 16:43
  • also it is possible to load up all Motors (pre-load) and then assign them to Products as needed. – Dennis Jul 2 '15 at 16:51
  • 1
    If it is just one, you don't need array or list, the Product object can have a property of motor which is another structure or class. One could then have a query that would join the product and motor. There nothing wrong with the mapper calling another mapper to map the motor as well. – Jon Raynor Jul 2 '15 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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