SPRING CONCEPTS

DAO · Data Access Object

Spring Concepts / DAO · Data Access Object

A DAO is a component that reads and writes persistent data. Its interface declares the available operations; an implementation class contains the code that performs them.

Understand the idea

DAO names an architectural responsibility, not a special Java keyword. A service asks for data operations through a DAO. The DAO talks to a database using JDBC, MongoTemplate, or another persistence API. Separating these responsibilities keeps HTTP handling and business rules away from database-specific details.

A concrete example

Browser → Controller → Service → DAO → Database

TodoDao dao = new MongoTodoDao(mongoTemplate);
// Declared type: TodoDao interface
// Actual object: MongoTodoDao implementation class

In the application

The Spring Boot labs use TodoRepository extends MongoRepository<Todo, String> for database access. This fills the data-access role; the labs do not require an extra hand-written DAO layer. The Servlet/JSP introduction stores todos in the browser session and has no database DAO.

An ordinary DAO interface does not produce database code by itself. Java cannot instantiate an interface with new TodoDao(). With a custom DAO, provide a class that implements it. Spring Data repository interfaces are a separate framework feature that supplies a runtime implementation.

Stage 10 versus Stage 11: repository and DAO

The product repository fulfills the DAO responsibility: it gives ProductService methods for accessing stored products. DAO emphasizes data access; a repository presents operations on application objects. These related ideas do not require two separate layers in this example.

In Stage 10 we write FileProductRepository, including its findAll() and findById() method bodies. In Stage 11 ProductRepository extends MongoRepository<Product, Integer>. Spring Data creates the repository implementation at startup; Spring injects that object into ProductService. Product is the handled Java type and Integer is its ID type.

StageActual data-access objectImplementation supplied by
10FileProductRepositoryOur Java code
11Spring Data repository implementing ProductRepositorySpring Data MongoDB
Illustrative example
// Stage 11: interface declaration
public interface ProductRepository
        extends MongoRepository<Product, Integer> {
}

// Calls made by ProductService
repository.findAll();
repository.findById(1);

Two findAll methods with different responsibilities

ProductService.findAll(boolean inStockOnly) is our own Java method. It calls repository.findAll() to obtain the products, then applies our stock rule. Spring Data supplies the inherited repository operation; it does not invent or implement our business rule.

An arbitrary DAO interface cannot implement itself. @Repository alone does not write method bodies. Stage 11 works because MongoRepository is a supported Spring Data repository interface. No extra hand-written ProductDao is required.

Interface versus implementation: where each belongs

Think of the interface as a contract: WHAT operations are available. The implementation class supplies HOW those operations work. A service field uses the interface type, while the object assigned to that field is an implementation instance.

PlaceExamplePurpose
ContractTodoDao interfaceDeclare findById and save.
Database layerMongoTodoDao implements TodoDaoCall MongoDB through MongoTemplate.
Business layerTodoDao field in a serviceUse the contract without choosing the database code.
Object assemblySpring configuration or new MongoTodoDao(...)Provide an actual implementation object.

1. TodoDao.java — declare the contract

Illustrative alternative for a Spring Boot MongoDB project using the existing com.example.todo.Todo model. Each block below is a separate Java file. These are not files to paste into the Servlet-only starter.

Illustrative example
package com.example.todo;

import java.util.Optional;

public interface TodoDao {
    Optional<Todo> findById(String id);
    Todo save(Todo todo);
}

2. MongoTodoDao.java — implement the database operations

This class implements every method in the contract. MongoTemplate performs the database work. Returning Optional makes the missing-record case explicit. @Repository marks this concrete component for Spring discovery; that annotation does not write these method bodies for you.

Illustrative example
package com.example.todo;

import java.util.Optional;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class MongoTodoDao implements TodoDao {
    private final MongoTemplate mongoTemplate;

    public MongoTodoDao(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @Override
    public Optional<Todo> findById(String id) {
        return Optional.ofNullable(
            mongoTemplate.findById(id, Todo.class));
    }

    @Override
    public Todo save(Todo todo) {
        return mongoTemplate.save(todo);
    }
}

3. DaoTodoService.java — depend on the interface

The service receives TodoDao through its constructor. If MongoTodoDao is the only matching bean in the scanned application, Spring can supply it. If multiple implementations are beans, choose one explicitly with @Qualifier or @Primary.

Illustrative example
package com.example.todo;

import java.util.Optional;
import org.springframework.stereotype.Service;

@Service
public class DaoTodoService {
    private final TodoDao todoDao;

    public DaoTodoService(TodoDao todoDao) {
        this.todoDao = todoDao;
    }

    public Optional<Todo> findById(String id) {
        return todoDao.findById(id);
    }
}

The declared field type is TodoDao. At runtime, that reference can point to a MongoTodoDao object. The service calls findById without containing MongoTemplate calls.

Understand the object reference

In this illustrative assembly snippet, mongoTemplate means an already configured MongoTemplate object:

Illustrative example
TodoDao dao = new MongoTodoDao(mongoTemplate);
DaoTodoService service = new DaoTodoService(dao);

new creates the concrete class. The interface type limits which operations callers see. In a Spring-managed application, constructor injection assembles this object graph instead of putting these new statements in a controller.

Can a DAO be just a class?

Yes. A small application can use a concrete DAO class directly without a separate interface. An interface is useful when it gives a meaningful boundary, supports another implementation, or helps substitute test data access. It is a design choice, not a rule that every DAO must have two files.

For example, a test can supply an in-memory TodoDao implementation. Switching to a different real database may still require changes to queries, mappings, configuration and behavior; an interface does not make every database interchangeable automatically.

What changes with Spring Data MongoRepository?

In the actual Spring Boot tutorial, use this repository interface rather than adding the illustrative DAO files above:

Illustrative example
package com.example.todo;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface TodoRepository
        extends MongoRepository<Todo, String> {
}

With repository scanning configured, Spring Data supplies the repository implementation at runtime. Common methods include save, findAll, findById and deleteById. An arbitrary interface named TodoDao does not get that behavior. The library-provided repository support is what makes this declaration work.

DAO and Repository: related, not identical

DAO emphasizes persistence operations and database access. Repository is a domain-oriented abstraction for retrieving and storing domain objects. In this course, TodoRepository performs the data-access role, but the two pattern names are not exact synonyms.

Keep the existing repository approach when following the runnable labs. The custom DAO examples explain the interface/class distinction; they are an alternative architecture, not another required layer between every service and repository.

Check your understanding

Which type appears in the service field? TodoDao, the interface. Which class is instantiated? MongoTodoDao. Where is the database call written? In MongoTodoDao. Who supplies the implementation in the repository-based labs? Spring Data.

See it in a working stage

Related concepts

Read the official documentation ↗
Java 21 · Spring Boot 4.1.1 · Edupoly