DAO pattern in java

The DAO (Data Access Object) pattern is a structural pattern used to separate the persistence logic from the business logic. It provides an abstraction layer for data access and ensures that changes in the underlying database do not affect the business logic.

Steps to Implement DAO Pattern in Java

1. Define the Entity Class

This class represents the table structure.


import java.io.Serializable;

public class User implements Serializable {
  private Long id;
  private String userName;
  private String firstName;
  private String lastName;

  public User() {}

  public User(Long id, String userName, String firstName, String lastName) {
    this.id = id;
    this.userName = userName;
    this.firstName = firstName;
    this.lastName = lastName;
  }
 // ... setters and getters 
}

2. Create a generic DAO Interface

This interface defines the database operations.



public interface Operations<T> {
  T findOne(final Long id);

  List<T> findAll();

  void create(final T entity);

  T update(final T entity);

  void delete(final T entity);

  void deleteById(final long entityId);
}

2.1 Create User DAO Interface

Into this interface will  be declared user entities' special operation 


import java.util.List;

public interface UserDao extends Operations<User> {

  List<User> selectAllPageable(int fromRow, int rows);

  int[] batchInsert(List<User> userList);

  int[] batchUpdate(List<User> userList);
}

3. Abstract implementation of DAO Interface 

This step can be optional because from Java 8, into interfaces we can have default implemented methods, but I prefer to have an  abstract class here 

 

public abstract class AbstractDAO<T extends Serializable> implements Operations<T> {
  private final DataSource dataSource;

  public AbstractDAO(DataSource dataSource) {
    this.dataSource = dataSource;
  }

  protected Connection getConnection() throws SQLException {
    return dataSource.getConnection();
  }

  @Override
  public T findOne(Long id) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public List<T> findAll() {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void create(final T entity) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public T update(final T entity) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void delete(final T entity) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  public void deleteById(final long entityId) {
    throw new UnsupportedOperationException("Not supported yet.");
  }
}


4 Implement DAO Interface (JDBC Example)

This class contains actual JDBC logic to interact with the database.


import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class UserDaoImpl extends AbstractDAO<User> implements UserDao {
  private static final Logger logger = LogManager.getLogger(UserDaoImpl.class);
 
 public UserDaoImpl(DataSource dataSource) {
    super(dataSource);
  }

  @Override
  public User findOne(Long id) {
    String sql = "select u.* from users u where u.id = " + id;
    User user = null;

    try (Statement statement = getConnection().createStatement();
         ResultSet result = statement.executeQuery(sql)) {
      while (result.next()) {
        user =
            new User(
                result.getLong("id"),
                result.getString("user_name"),
                result.getString("first_name"),
                result.getString("last_name"));
      }

    } catch (SQLException e) {
      logger.error(e);
    }

    return user;
  }

  @Override
  public User findByUsername(String userName) {
    return null;
  }

  @Override
  public List<User> selectAllPageable(int fromRow, int rows) {
    List<User> users = new ArrayList<>(rows);
    String sql = "SELECT * FROM users u  LIMIT" + fromRow + "," + rows;
    try (Statement statement = getConnection().createStatement();
         ResultSet result = statement.executeQuery(sql)) {
      while (result.next()) {
        users.add(
            new User(
                result.getLong("id"),
                result.getString("user_name"),
                result.getString("first_name"),
                result.getString("last_name")));
      }

    } catch (SQLException e) {
      logger.error(e);
    }
    return users;
  }

}

4. Create a Test Class

This will test the DAO implementation.


public class UserDaoImplTest {
    private UserDaoImpl userDao;

    @Before
    public void setUp() throws Exception {
        // About this DataSourcesConfiguration we will have other article 
        DataSourcesConfiguration dataSourcesConfiguration = new DataSourcesConfiguration();
        userDao = new UserDaoImpl(dataSourcesConfiguration.getDataSources());

    }

    @Test
    public void findOneTest() {
        User user = userDao.findOne(1l);
        assertNotNull(user);
        assert user.getId().equals(1l);
    }

    @Test
    public void selectAllPageableTest() {
        List<User> userList = userDao.selectAllPageable(0, 6);
        assert !userList.isEmpty();
        assert userList.size() == 6;

        List<User> userList2 = userDao.selectAllPageable(0, 8);
        assert !userList2.isEmpty();
        assert userList2.size() == 8;
    }

    @Test
    public void create() {
        User user = new User();
        user.setUserName("This email address is being protected from spambots. You need JavaScript enabled to view it.");
        userDao.create(user);
        User userCreated = userDao.findByUsername("This email address is being protected from spambots. You need JavaScript enabled to view it.");
        assertEquals(userCreated.getUserName(),"This email address is being protected from spambots. You need JavaScript enabled to view it." );

    }

    @Test
    public void update() {
        User user =  userDao.findByUsername("This email address is being protected from spambots. You need JavaScript enabled to view it.");
        user.setUserName("This email address is being protected from spambots. You need JavaScript enabled to view it.");
        User updated =  userDao.update(user);
        assertEquals(updated.getUserName(), "This email address is being protected from spambots. You need JavaScript enabled to view it.");

    }

    @Test
    public void delete() {
        userDao.deleteByUserName("This email address is being protected from spambots. You need JavaScript enabled to view it.");
        assertNull(userDao.findByUsername("This email address is being protected from spambots. You need JavaScript enabled to view it."));
    }

}

Advantages of Using DAO Pattern

  1. Separation of Concerns – Keeps data access logic separate from business logic.
  2. Easier Maintenance – Changes in the database schema require updates only in the DAO layer.
  3. Scalability – Easier to migrate to a different database (e.g., switching from MySQL to PostgreSQL).
  4. Reusability – DAO classes can be reused across multiple projects or applications.

Enhancements