DAO Pattern

The pattern allows:

  • an abstract interface to some type of database or persistence mechanism, providing some specific operations without exposing details of the database.

DAO Pattern


It is a structural core J2EE pattern alongside with DTO/Entity (Data transfer object) and DBO (Data Business Object). Generally by means of the pattern you can have the application architecture where you business model doesn’t deal with data storage (e.g. DB) directly, but through an abstract layer with a simple interface (CRUD – create, read, update, delete).

The DAO pattern is used by most of mainstream frameworks, though it can be other patterns, but based on DAO. Thereby, Zend Framework has for the data access abstraction layer the Table Data Gateway pattern from Martin Fowler's POEAA. Symfony uses Doctrine library. Ruby On Rails uses an ActiveRecord implementation bound to the database layer.


PHP Example

The example shows very simple DAO implementation, based on Hypernate interface.

<?php
/*
 * @category Design Pattern Tutorial
 * @package DAO Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */

abstract class Dao_Abstract
{
    protected $_connection;
    protected $_primaryKey;
    protected $_tableName;

    public function  __construct($connection)
    {
        $this->_connection = $connection;
    }
    public function find($value, $key = NULL)
    {
        if (is_null($key)) {
            $key = $this->_primaryKey;
        }
        return $this->_connection->fetch(sprintf(
            "SELECT * FROM %s WHERE %s = '%s'", $this->_tableName, $this->_primaryKey, $value));
    }
    public function findAll($value, $key = NULL)
    {
        //..
    }
    public function insert($assocArray)
    {
        //..
    }
    public function update($assocArray)
    {
        //..
    }
    public function delete($key = NULL)
    {
        //..
    }
}

class Dao_User extends Dao_Abstract
{
    protected $_primaryKey = "userId";
    protected $_tableName = "User";

    public function findByEmail($email)
    {
        return $this->find($email, 'email');
    }
}

/**
 * Usage
 */
$user = Dao_User(Lib_Db::getInstance('masterDb'));
$user->findByEmail('admin@thewall.we');

JS/ES5 Example

/*
 * @category Design Pattern Tutorial
 * @package DAO Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */
(function() {
var DataAccess = function() {
    return {
        get: function(controller, params, callback) {
            // Here can be XMLHttpRequest
            callback({
                'userId' : 1,
                'name' : 'Jon Snow',
                'email' : 'admin@thewall.we'
            });
        }
    }
}

var Dao_Abstract = function() {
    return {
        fetch : function(value, key) {
            if (typeof key === "undefined") {
                key = this._primaryKey;
            }
            this._dataAccess.get(this._controllerName, {'value' : value, 'key' : key}, this.onMessage);
        }
    }
}

var Dao_User = function(dataAccess, entity) {
    this._dataAccess = new DataAccess();
    this._controllerName = 'UserController';
    this._primaryKey = 'userId';
}
Dao_User.prototype = new Dao_Abstract();
Dao_User.prototype.fetchByEmail = function(email) {
     this.fetch(email, 'email');
}

/**
 * Usage
 */
var user = new Dao_User(new DataAccess());
// User can be retrieved asynchronously, so onMessage handler will server to catch output
user.onMessage = function(user) { console.log(user); };
user.fetchByEmail('email@email.com');

// Output
// -> Object { userId=1, name="Jon Snow", email="admin@thewall.we"}

}());