40

What should be the best way to design a DAO class ?

Approach#1: Design DAO class as an object.

class Customer {
//customer class
}

class CustomerDAO {
  public void saveCustomer(Customer customer) {
  //code
  }

  public Customer getCustomer(int id) {
  //code
  }
}

//Client code
class client {
  public static void main(String[] args) {

   CustomerDAO customerDAO = new CustomerDAO();
   Customer customer = new Customer();
   customerDAO.saveCustomer(customer);
  }
}

Approach#2: Design DAO class with static methods (aka static class)

class Customer {
//customer class
}

class CustomerDAO {
  public static void saveCustomer(Customer customer) {
  //code
  }

  public static Customer getCustomer(int id) {
  //code
  }
}

//Client code
class client {
  public static void main(String[] args) {

   Customer customer = new Customer();
   CustomerDAO.saveCustomer(customer);
  }
}

In approach#1, I have to create an object of DAO class in all the client code (other option is to pass the reference of DAO all around). while in approach#2, I do not have to create the object and the static methods can be designed with no state tracking.

So which approach is the best in design of DAO classes ?

nibin012
  • 1,793
  • 2
  • 15
  • 14
  • 4
    Use approach #1 and inject references to it using an IOC container like Spring – Sean Patrick Floyd Aug 29 '11 at 15:16
  • 3
    It's strange nobody mentioned such a nice and informative tutorial by [BalusC](http://stackoverflow.com/users/157882/balusc): [DAO tutorial - the data layer](http://balusc.blogspot.com/2008/07/dao-tutorial-data-layer.html). Read it and you will find the answers to many DAO design and implementation related questions. – informatik01 Dec 06 '13 at 16:40

5 Answers5

38

I would recommend approach #1, but would use Spring for dependency injection rather than instantiating DAOs directly.

This way, for unit testing the client code, you can substitue mock DAOs, and verify that the correct DAOs are invoked with the appropriate arguments. (Mockito is useful here.)

If you use static methods, then unit testing is much more difficult, since static methods cannot be overridden.

Eric Wilson
  • 57,719
  • 77
  • 200
  • 270
  • 5
    +1 I was too lazy to write this answer myself. But it would have been pretty identical to this one :-) – Sean Patrick Floyd Aug 29 '11 at 15:21
  • What if one of customers(user) from DAO object is representing current logged-in customer(user). Would you provide method like getCurrentCustomer() or would it be transparent for DAO class and this user always be obtained by id? – Piotr Mar 14 '14 at 00:44
  • 1
    @Piotr I would think that the DAO should not be concerned with from whom the request originated. – Eric Wilson Mar 14 '14 at 01:12
  • So where would you store logged-in user's ID? Would you pass it from one place to another? Would you store it in some singleton storage class? Maybe you happen to know any good example of Logged-in user and/or User DAO design? – Piotr Mar 14 '14 at 05:11
  • @Piotr If you add some more context, this could be a good question for SO. That would provide much more visibility than comments on a 2.5 year-old question. – Eric Wilson Mar 14 '14 at 10:19
  • @EricWilson, ok. Good idea. I didn't see any questions about it here. – Piotr Mar 14 '14 at 18:00
12

To have more abstraction :

interface IDAO<T> {

  public save(T t);
  public T getById(int id);
  //...etc

}

then

public CustomerDao implements IDAO<Customer>{
   public save(Customer c){
        //Code here
    }
   public Customer getById(int id){
      //Code here
    }
}

and DAO tO another domain

public UniversityDao implements IDAO<University>{

     public save(University u){
       //Code here
      }
     public University getById(int id){
        //Code here
     }
}

Now the presentation layer or the main Class will contain the code like this :

IDAO  dao;
dao=new CustomerDao();
//...
dao=new UniversityDao();
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
6

I would go for option 1 as well but I would also recommend you to program to interfaces. Create an interface that sets which functions the DAO has to provide and then you can implement those with different classes depending on your needs.

public interface CustomerDao {
    public void saveCustomer(Customer customer);

    public Customer getCustomer(int id);
}

Then you can have class SimpleCustomerDao implements CustomerDAO {/*code here*/}.

In your main (and everywhere else you need it) you'll have:

//Note that you have an interface variable and a real class object 
CustomerDao customerDao = new SimpleCustomerDao();

You can figure out the benefits of doing this!

And yes, if you use Spring or Guice then do use Dependency Injection!

Marsellus Wallace
  • 17,991
  • 25
  • 90
  • 154
5

Refer to article how to write a generic DAO (using Spring AOP): Don't repeat the DAO!

You can find examples of generic DAO implementations for your technology stack (just google "Don't repeat the DAO my_technology").

Andrey
  • 6,526
  • 3
  • 39
  • 58
0

I would Prefer the Layered Approach, and What This approach simply tell us is:

  1. You are having your model class Customer
  2. You are having a contract with client through Interface CustomerDAO

    public interface CustomerDAO{
    
        public void saveCustomer(Customer customer);
        public Customer getCustomer(int id);
    }
    
  3. You are having a concrete Implementation like CustomerDAOImpl

    public class CustomerDAOImpl extends CustomerDAO{
    
        public void saveCustomer(Customer customer){
          saveCustomer(customer);
        }
    
        public Customer getCustomer(int id){
          return fetchCustomer(id);
        }
    }
    

Then Write a Manager to Manage these or Encapsulating some other DAOs like:

public class ManagerImpl extends Manager{
    CustomerDAO customerDAOObj;

    // maybe you need to collect
    // all the customer related activities here in manger
    // because Client must not bother about those things.

    UserBillingDAO userBillingDAOObj; 

    public void saveCustomer(Customer customer){
      customerDAOObj.saveCustomer(customer);
    }

    public Customer getCustomer(int id){
      return customerDAOObj.fetchCustomer(id);
    }

    // Note this extra method which is defined in 
    //UserBillingDAO which I have not shown, but you are exposing 
    //this method to your Client or the Presentation layer.

     public boolean doBillingOFCustomer(id) {
        return userBillingDAOObj.doBilling(id);
    }
}

Now the presentation layer or the main Class will contain the code like this:

public static void main(String... ar){
     Manager manager = new ManagerImpl();
     manager.saveCustomer();
    // or manager.doBillingOfCustomer(); // etc
}
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
Tiwari
  • 329
  • 2
  • 7
  • ` public void saveCustomer(Customer customer){ saveCustomer(customer); }` LOL + you have errors like `public Customer getCustomer(int id);` and then `customerDAOObj.fetchCustomer`. Not to mention your formatting...Fix those - -1 till then – Mr_and_Mrs_D Nov 07 '13 at 11:22