Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DAO vs ORM - Concept explained in the context of Sequelize.js

I've been working with Sequelize.js recently and come across the term "DAO" pretty frequently. Coming from ActiveRecord (in Rails), the idea of an ORM seems pretty straight forward.

Could someone explain to me what a DAO is? How does it differ from an ORM? How does it result in more modular code/prevent abstraction leaking?

Edit: After reading things like: https://www.reddit.com/r/learnprogramming/comments/32a1fr/what_is_the_general_difference_between_dao_and_orm/

It feels/seems like a DAO could be thought of as a singular "model" - as in the context of ActiveRecord, my User instance would be considered a DAO in that it: "abstracts the implementation of a persistent data store away from the application and allows for simple interaction with it"?

like image 669
The Dembinski Avatar asked Jan 05 '17 21:01

The Dembinski


People also ask

What is DAO and ORM?

ORM and DAO are orthogonal concepts. One has to do with how objects are mapped to database tables, the other is a design pattern for writing objects that access data. You don't choose 'between' them. You can have ORM and DAO is the same application, just as you don't need ORM to use the DAO pattern.

What is DAO in Sequelize?

So a DAO is just "an object that can execute SQL and return results in some basic data structure native to the programming language". An ORM will ultimately use a DAO to communicate with the database, but provides a whole lot more on top.

What is ORM in Sequelize?

Sequelize is a Node. js-based Object Relational Mapper that makes it easy to work with MySQL, MariaDB, SQLite, PostgreSQL databases, and more. An Object Relational Mapper performs functions like handling database records by representing the data as objects.

What is DAO in JS?

Data Access Object Pattern or DAO pattern is used to separate low level data accessing API or operations from high level business services. Following are the participants in Data Access Object Pattern. Data Access Object Interface - This interface defines the standard operations to be performed on a model object(s).


2 Answers

I am not too familiar with ActiveRecord but yes, it sounds like your User instance is indeed a DAO.

The previous answer has some confusing aspects in it which I hope to clarify.

According to Oracle's description of the DAO pattern it:

  • separates a data resource's client interface from its data access mechanisms
  • adapts a specific data resource's access API to a generic client interface

The DAO pattern allows data access mechanisms to change independently of the code that uses the data.

That being said, manually executing a SQL statement using a language's SQL driver would almost never be referred to as a DAO. Firstly, it doesn't abstract the data access mechanism enough to be of any practical value. You couldn't, say, swap your DB for a NoSQL backend without having to reimplement ActiveRecord's execute method to map SQL queries into the new backend's API.

That being said, some practical examples:

// Cloudscape concrete DAO Factory implementation
import java.sql.*;

public class CloudscapeDAOFactory extends DAOFactory {
  public static final String DRIVER=
    "COM.cloudscape.core.RmiJdbcDriver";
  public static final String DBURL=
    "jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";

  // method to create Cloudscape connections
  public static Connection createConnection() {
    // Use DRIVER and DBURL to create a connection
    // Recommend connection pool implementation/usage
  }
  public CustomerDAO getCustomerDAO() {
    // CloudscapeCustomerDAO implements CustomerDAO
    return new CloudscapeCustomerDAO();
  }
  public AccountDAO getAccountDAO() {
    // CloudscapeAccountDAO implements AccountDAO
    return new CloudscapeAccountDAO();
  }
  public OrderDAO getOrderDAO() {
    // CloudscapeOrderDAO implements OrderDAO
    return new CloudscapeOrderDAO();
  }
  ...
}

As shown, the DAO factory sets up any connections with the underlying DB. This configuration is abstracted from the client.

// Interface that all CustomerDAOs must support
public interface CustomerDAO {
  public int insertCustomer(...);
  public boolean deleteCustomer(...);
  public Customer findCustomer(...);
  public boolean updateCustomer(...);
  public RowSet selectCustomersRS(...);
  public Collection selectCustomersTO(...);
  ...
}

As you can see, the DAO is meant to provide an object with a narrow interface to control and abstract access to the data layer. At any time, one could reimplement findCustomer to query a NoSQL DB and the calling code wouldn't need to change. Thus "The DAO pattern allows data access mechanisms to change independently of the code that uses the data."

The DAO illustrated above may use an ORM library in the implementation to map the DB objects into models of the calling code or the implementation may perform the mapping itself. In any case, if the interface were changed so that findCustomer returns a plain object and did no mapping, it would still be a DAO. A DAO does not need an ORM but often uses one.

An ORM can potentially perform all of its DB access using raw methods like the programming language's method for establishing TCP connections. So An ORM does not need a DAO but often uses one.

The fundamental feature of an ORM is that it maps DB objects into domain models. If an ORM library also handles communications with the DB, whether it uses a DAO or opens TCP connections to the DB, then it is itself also a DAO.

like image 154
papiro Avatar answered Oct 13 '22 14:10

papiro


Here's some thoughts which might help clarify it for you. I'm more familiar with ActiveRecord than Sequelize, so I'll run with that, but the concepts should be the same for both.

You have a database. You can, completely independent of Rails (eg. using a database admin tool), go and run a query on that database - something like "select * from users limit 1". But that just gives you a set of results in some admin window, which aren't much use to your Rails app. You want to be able to execute SQL from your Rails app, and get data back in a form that Ruby/Rails can work with. You need to Access your Data through some kind of ruby Object - you need a Data Access Object, or DAO.

In rails, you could run the query above with something like:

result = ActiveRecord::Base.connection.execute("select * from users limit 1")

The result variable won't know or care about your User model. All it will contain is essentially a list of plain ruby Hash instances, like:

{
  "id" => "1234",
  "email" => "[email protected]",
  "first_name" => "Fred",
  "last_name" => "Flintstone",
}

If you wanted to update the first_name to Bob, you couldn't just edit that hash and call save on it - it's just a plain old hash, just the data and no extra smarts. So you'd have to write your own SQL again, and get Rails to execute it for you:

ActiveRecord::Base.connection.execute("update users set first_name = 'Bob' where id = 1234")

So what you're using in this context is basically just Rail's DAO, without using it's ORM.

The ORM is like a layer on top of the DAO. You can have a DAO without an ORM, but you can't have an ORM without a DAO. The ORM, or Object Relational Mapper will Map concepts / records in your Relational database with Objects in your programming language (ie, Ruby). So, if you wanted to do the stuff above, using Rail's ORM rather than using it's DAO, it might look like:

user = User.find(1234)
user.name = 'Bob'
user.save!

See how much nicer it is using an ORM? Now, the snippet above, using the ORM, will still essentially just execute the same SQL we detailed earlier. The ORM just abstracts away more of the details and provides smarter objects to save us a bunch of extra work.

Again, the concepts demonstrated are transferable to Sequelize / Javascript and other langs/frameworks.

So a DAO is just "an object that can execute SQL and return results in some basic data structure native to the programming language". An ORM will ultimately use a DAO to communicate with the database, but provides a whole lot more on top.

like image 25
joshua.paling Avatar answered Oct 13 '22 14:10

joshua.paling