How does a DAO differ from a DataMapper? Is a DataMapper not just a type of DAO object?

If they are indeed different, what is the role of each and what methods might a DAO have as opposed to a DataMapper? From what I've seen of DataMapper examples they usually have get/find, save and delete method, which is generally the methods I associate with a DAO.

My understanding of a DAO is that it imposes a common interface for accessing data from a data source. Would this be a correct understanding of the role of a DAO?

I imagine this might have been asked before, but I'm really just trying to get a clear understanding of how the two differ. I'll continue searching for discussions that outline how they differ if at all.

    To my mind DAO is a faily generic term for describing an object that persists data via a common interface. In a given application there may be many objects which have a common interface and so might be considered DOAs. There are quite a few patterns which have this characteristic (active record, table data gateway etc).

    Martin Fowler describes the data mapper as a pattern for mapping an object to a persistence layer. The need arises because the structure that works for an object graph does not necesarily work in a relational database. In this sense a data mapper is a form of DAO. The data mapper pattern differs from active record and table data gateway since the object being persisted need not have any bearing on the underlying persistence layer, the mapper hides all that away.

      The explanation of DAO really cleared that up.

      Just so I'm understanding you correctly with respect Data Mapper, I'm going to present an example and you let me know if I'm right.

      I have a 'Message' model, for this particular model I'll instantiate a mapper that uses db as a persistent store. A message has a body, date, status and sender. The message may also have several recipient.

      This results in a db structure of:

      sender: [U]id[/U] (primary key), name (varchar), email (text), status (enum['active','inactive'])
      
      message: [U]id[/U] (primary key), [U]sender_id[/U] (int), body (text), date (datetime), status (enum['sent','draft'])
      
      message_recipient: [U]message_id[/U] (int), [U]sender_id[/U] (id)
      

      Using my mapper I would handle the relation between the three tables. So a method like 'getMessage' would return my message complete with sender and recipients.
      i.e.

      // SQL Mapper example
      $message = new Message(new SQL_MessageMapper());
      $message->getMessage(492);
      
      $sender_name = $message->sender->name;
      $recipients = '';
      foreach($message->recipient as $recipient) {
        $recipients .= $recipient->name;
      }
      $message_body = $message->body;
      
      

      An XML store might have the recipients as part of the message itself, but by implementing the mapper interface the result of my getMessage should still be the same.
      i.e.

      // XML store
      <message id="492" sender_id="5" status="active">
        <body>Some really clever message, voicing my displeasure about the state of affairs.</body>
        <date>2010-05-12 11:23:09</date>
        <status>draft</status>
        <recipients>
           <recipient>5</recipient>
           <recipient>29</recipient>
           <recipient>439</recipient>
        <recipients>
      </message>
      
      // XML Mapper example
      $message = new Message(new XML_MessageMapper());
      $message->getMessage(492);
      
      $sender_name = $message->sender->name;
      $recipients = '';
      foreach($message->recipient as $recipient) {
        $recipients .= $recipient->name;
      }
      $message_body = $message->body;
      
      

      Does all this seem correct?

        That seems correct to me. I might have the mapper return instances of Message as it would mean the Message object itself has no knowledge of how it's persisted.

        interface MessageMapper
        {
          /**
           * @param int $id message ID
           * @return object $message Message
           */
          public function get( $id );
          /**
           * @param object $message Message
           * @return boolean
           */
          public function put( Message $message );
        }
        
          17 days later

          Here's a follow up to the initial question.

          What's the most logic place to define relationships?

          If you look at my previous example you'll notice that Message may have multiple recipient. The SQL example uses a link table 'message_recipient', whereas in the XML example recipients are stored as part of the message element.

            Well, "define" is a bit vague. In a sense you've already partially defined the relationship by saying that each message has recipients.

            I take it that what you are asking about is the most appropriate place to implement (and ensure) that relationship in a given system. And for the most part that extends across the board: in a relational database it's a relation, so it gets its own table; in an XML schema there'd be a rule to say that <message> elements have a <recipients> child containing zero or more <recipient> children (which personally for the purposes of type safety I'd leave empty and use an attribute to hold the recipient id); in an object model the Message object would have an interface to return a collection of its Recipients.

            It's at this point where methods like UML and modelling software start making their entrance. It's feasible to consider taking a UML diagram and automatically generating the database schema, XML schema, an (abstract) DAO library to extend, and suitable mappers from it. Then the diagram becomes the "definition". This is called "model-driven architecture".

            Just incidentally, regarding the use of XML schema and data mapping (data binding), I've stumbled across a W3 working group note on schema patterns which looks interesting.

              Unfortunately my knowledge of UML is limited, I did however have a look into MDA.

              Many of the examples I've seen define the relationship within the model, which seems logical enough except that some of those relationships work on the assumption that a RDMS is used.

              My thought was to define the basic relationship in the model, then leave mapping of those relationships to my mapper.

              Here's what I mean.

              class Message
              {
                 $relationship = array(
                   'HasMany' => 'Recipient' 
                 );
              
                public function __construct(Mapper $mapper)
                {
                   $this->mapper = $mapper;
                   $this->mapper->setRelationship($this->relationship);
                }
              
                 // remaining object body....
              }
              
              class SQL_MessageMapper extends Mapper
              {
                public function setRelationship(array $relationship)
                {
                 //......
                }
              }
              
              

              Not sure how much sense all this makes.

                6 days later

                As Weedpacket points out, this is a complex task that requires some careful forethought. While a simple "one to many" relationship is quite straight forward, trying to model complex relationships can be rather difficult. Certainly beyond anything I would feel comfortable tackling here 😉

                I think you are on the right lines in that the model itself should define it's relationships, but leave the fetching of relations to a mapper.

                Have you looked into some of the relevant frameworks out there? Django, Doctrine, Propel.

                  5 days later

                  I haven't looked at any of those, though I did have a brief look at Doctrine.

                  The problems I've come upon so far, is the has many and belongs to many relationships. The basic model I'm working with would need to refactored to prevent any sort recursion.

                  I suspect it would take two or three tries at this to get something that is efficient.

                    Zstar Electronic Co.Ltd, Sell fire cards for DS/NDSL/NDSi, also have Wii, DSiLL, NDSi, NDSL, PSP2000, PSP3000, PS2, PS3, PSP go, PSP, Xbox360 accessories, all kinds of phones are available
                    www.zstar.hk
                    WWW.TIGERSUPERMALL.COM

                      Write a Reply...