How does the DAO Standard work?

Asked

Viewed 53,541 times

38

I researched and read about DAO (Data Access Object Standard), but I’m not getting to understand how it works and how is its structure, it is also responsible for the business rules of an application? Or is he just responsible for CRUD and by transactions and connections?

Note: Preferably, if you can show your implementation and practical operation in Java.

  • Why The Java Tag?

  • 1

    See the edition, I forgot to mention that I would like to see how it is used in Java.

  • 2

    The DAO is the intermediary with the database, it makes connection and transactions with this. Who handles the business rule is the model. But they are concepts that cause a little confusion even for those who do not have custom with even Patterns design.

  • @Diegofelipe is he part of some other pattern? Or is the DAO one thing? I hope someone responds too, the staff is using it in college no one else understands what it is and how it works to be able to use it.

3 answers

53


Definition

In summary, DAO is a pattern of projects where an object:

  • provides an interface that abstracts data access;
  • reads and writes from the data source (database, file, memory, etc.); and
    • encapsulates the access to the data, so that the other classes do not need to know about it.

Architecture

In a common web application following the MVC model, the Daos are together with the Model doing support work, integrating the data source to the system object model.

inserir a descrição da imagem aqui

Source: Introduction to the JDBC

Responsibilities

Following the principle of sole responsibility, a DAO should not be responsible for more than access to data.

Defining who does what can be a problem when we think about the architecture of a system, but much of it is because we mix things up.

If you look at the diagram above, it is easy to identify the responsibility of each element.

Suppose the user is accessing the home page of the web system. Then a common interaction could be:

  1. A controller receives the user’s request
  2. That one controller calls the method of service suitable to get the information for that page
  3. The service calls one or more methods of Daos to obtain the necessary information and returns the data to the controller
  4. The controller receives the data and redirects the user to a view that will render the page’s HTML

Additionally, we have to:

  • Controllers perform logic related to user navigation on the system, i.e., which URL or action displays which page.
  • Services execute system logic, which can include managing transactions and processing data

Therefore, in general, each DAO method should make a single read or write to the database and should not control transactions or perform additional operations, such as making changes to the data received from the service.

I can tell from experience that it is often a temptation for you to put business rules or transactional control in the DAO, after all it is a place where all information will eventually pass. But sooner or later it will conflict with some other part of the system. Therefore, if there is a common rule to be applied in an entity, create a specific service for it and have all other services point to it.

Implementation

The advantage of using a specific class for data access is to avoid spreading Sqls everywhere, making the maintenance and evolution of a system a nightmare.

In general, the accesses to the data are grouped by similarity, for example, one class per table. However, it is not always that this makes sense, especially when the system is not only made of simple registrations (CRUD).

A clear example are systems that have advanced searches in which they access multiple tables. In this case, each situation needs to be analyzed case by case. In the case of searches, a specific DAO would be interesting.

Using interfaces is optional. See, Java has a bad reputation for using many interfaces, but this has its reasons, for example:

  • Allow multiple implementations for different databases without changing the system
  • Allow different versions to coexist in the same version of the system (this may be useful in some cases, such as when some field may or may not exist and you want to update the system without requiring field creation)
  • Facilitate unit testing by creating Fakes implementations of Daos, for example, that use lists in memory, although frameworks like Mockito can generate mocks dynamically without an interface

Interfacing

Have a very simple but complete example on my Github of a DAO encapsulating the entity Usuario.

The interface looks like this:

public interface UsuarioDao {
    Usuario findByNomeUsuario(String string);
    void atualizarUltimoAcesso(Integer id, Date data);
}

And the implementation using Spring JDBC Template:

public class UsuarioDaoImpl implements UsuarioDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Usuario findByNomeUsuario(String nomeUsuario) {
        try {
            return jdbcTemplate.queryForObject(
                    "select * from usuario where nome_usuario = ?", 
                    new UsuarioRowMapper(), 
                    nomeUsuario);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    public void atualizarUltimoAcesso(Integer id, Date data) {
        jdbcTemplate.update(
                "update usuario set ultimo_acesso = ? where id = ?", data, id);
    }

}

Sem Interface

The same interface-free DAO and using pure JDBC gets like this:

public class UsuarioDao {

    private DataSource ds;

    public void setDataSource(DataSource ds) {
        this.ds = ds;
    }

    public Usuario findByNomeUsuario(String string) {
        Connection con = null;
        PreparedStatement ps = null;
        try {
            con = ds.getConnection();
            ps = con.prepareStatement("select * from usuario where nome_usuario = ?");
            ps.setString(1, string);
            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                Usuario usuario =  new Usuario();
                usuario.setId(rs.getInt("id"));
                usuario.setNomeUsuario(rs.getString("nome_usuario"));
                usuario.setSenha(rs.getString("senha"));
                usuario.setNome(rs.getString("nome"));
                usuario.setUltimoAcesso(rs.getTimestamp("ultimo_acesso"));
                return usuario;
            } else {
                return null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void atualizarUltimoAcesso(Integer id, Date data) {
        Connection con = null;
        PreparedStatement ps = null;
        try {
            con = ds.getConnection();
            ps = con.prepareStatement("update usuario set ultimo_acesso = ? where id = ?");
            ps.setTimestamp(1, new java.sql.Timestamp(data.getTime()));
            ps.setInt(2, id);
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

We should use DAO these days?

Many would say no.

Orms like Hibernate or Eclipselink try to do all the heavy lifting to move the data between the objects and the tables. I have seen systems that directly manipulated JPA entities in business rules.

I would say that kind of solution is not scalable, which means it will create problems as the system grows. Precisely because of this, many use the Repository project standard, which is a slightly different type of DAO, even when using JPA.

In my opinion, the DAO standard is still, in general, the best way to implement the interface with the database in a system. I say this because interacting with the bank is a responsibility that is part of almost every system and, if you do not put in the DAO, will end up putting somewhere else. And you don’t want to mix responsibilities, go?

  • 5

    I wish I could vote for that answer several times. Very good!

12

The DAO standard has the main purpose of abstracting the access to the data source of your application (usually a database such as postgresql, mysql, mongodb, etc.) from the parts that use or provide this data. The problem he tries to solve is that the source of his data may change, may be for example that you currently own a production application made over mongodb however just discovered that this has certain data consistency problems that you can not tolerate and decided to migrate to a bank that guarantees greater integrity, and in this scenario if your bank access functions are mixed with parts of the logic of your code (such as the business rules for example) you would be required to refactor-lás, which is a problem because given that your code is stable you do not want to keep making changes that can cause it to break. If you have a separate DAO layer from your logical layer changing the data source becomes simply a matter of creating a new access interface for the new source, keeping your business rules untouched.

The "classic" DAO is divided into three parts, an interface that defines the methods that the access object will provide, the class that represents its data model and the class that performs data access, example for the case of its hypothetical application that has an entity Curso and currently uses mongodb:

Data model:

public class Curso {
    public long id;
    public String nome;

    public Curso(long id, String nome) {
        this.id = id;

        // finja que aqui existem
        // regras hiper complicadas de processamento
        // da variável "nome"

        this.nome = nome;
    }
}

Interface defining the methods of access to the bank:

interface CursoDAO {
    public Curso create(String name);

    public void update(long id, Curso curso);

    public void delete(long id);

    public Curso findByName(String name);
}

Finally your DAO implementation accessing the bank (mongodb):

public class CursoDAOMongodb implements CursoDAO {

    public Curso create(long id, String name) {
        // realiza a conexão necessária com a mongodb
        MongoClient mongoClient = new MongoClient();
        DB db = mongoClient.getDB("minha incrivel database");   

        DBCollection table = db.getCollection("curso");
        document.put("id", id);
        document.put("name", name);
        table.insert(document);

        return new Curso(id, name);
    }

    public Curso findByName(String name) {
        MongoClient mongoClient = new MongoClient();
        DB db = mongoClient.getDB("minha incrivel database");   
        BasicDBObject searchQuery = new BasicDBObject();
        searchQuery.put("name", name);

        // etc, pega os dados da query e retorna um new Curso com eles
    }

    public void delete(long id) {
        // realiza a conexão necessária com a mongodb e executa o DELETE no banco
    }

    public void update(long id, Curso curso) {
        // realiza a conexão necessária com a mongodb e executa o UPDATE no banco
    }
}

In your code that consumes and provides the data to the database you would have something like this:

// digamos que suas regras de negócio estejam na Main
public class Main() {

    static public CursoDAO getDbAcessorForCurso() {
        return new CursoDAOMongodb();
    }

    public static void main(String javaehverborragico[]) {

        String[] nomes = {"design", "pattern", "dao"};

        List<Curso> cursos = new ArrayList<Curso>();

        CursoDAO dbAcessor = Main.getDbAcessorForCurso();

        // criando cursos
        for (String nome : nomes) {
            Curso novoCurso = dbAcessor.create(nome);
            cursos.add(novoCurso);
        }

        // ...
        // realize outras operações de delete ou select usando
        // dbAcessor
    }
}

Note the method getDbAcessorForCurso, he is responsible for returning to you the object of your current access DAO which in this case is the one that uses mongodb. Now, continuing on the idea of the beginning of the answer, you are disillusioned with Nosql and want to return to a good old relational DBMS, let’s say postgresql, what do you do? only creates a new implementation for CursoDAO, this time one that uses postgresql:

public class CursoDAOPostgresql implements CursoDAO {

    public Curso create(long id, String name) {
        // realiza a conexão necessária com a mongodb
        Connection c = DriverManager.getConnection("jdbc:postgresql://localhost:5432/minha incrivel database");

        Statement stmt = c.createStatement();
        String sql = "INSERT INTO curso (id, name) VALUES (" + id + ", " + name + ") ";
        stmt.executeUpdate(sql);

        stmt.close();
        c.commit();
        c.close();

        return new Curso(id, name);
    }

    // ... outros métodos de CursoDAO, mesma ideia.
}

Now everything is ready for you to use postgresql instead of mongodb without the rest of your application noticing the difference, just change the method that returns your DAO object to return your new image:

public class Main() {

    static public CursoDAO getDbAcessor() {
        return new CursoDAOPostgresql();
    }
    ...

Okay, you migrated from one database to another by exclusively altering the part that interacts with the data source, the DAO implementation, no changes in the middle of your data model Curso or its business rules which in this case are in Main.

Two final notes:

  1. This is an extremely simplified example (and look at the size of the thing), maybe the advantages are not so evident on this scale so try to imagine more complex situations with numerous business rules permeating the code.
  2. DAO is a Java standard at the heart, which means it often generates tons of classes and interfaces. Although it is a great Pattern and solve real problems care not to abuse, you do not need to follow it to the letter, simplified implementations are usually preferable if you are not drawing mega Erps where changing a less flexible part of the system can last two generations of your family. Also, if you’re simply prototyping a system or doing something really simple it doesn’t make sense to complicate your code with a Pattern whose advantages will never really be used. Always analyze the situation before leaving using patterns, it may be that the addition of complexity they bring does not compensate for the flexibility gained.
  • But if I’m going to use a DAO class per model class, there’s no point in me doing an interface, right? After all, I will only have an implementation of the DAO of that specific model. Unless I made an interface that in the searches for example, returned an Object, then yes I could use this interface for all the DAO of my system. But I suspect that’s not a good idea either, right? @Brunorb

6

TL;DR

The DAO or DAL Standard is nothing more than part of the architectural concept Three-Tier(three Layers in Portuguese) this programming model aims to distinguish the layers of presentation, processing, and access to data physically.

In short you would basically divide the monolithic model of applications into a model where each layer has a responsibility within the system.

The distribution of an application in 3 layers for being conceived in different assemblies (Packages) and even in different physical machines communicating through services and webservices among other means.


Three-Tier


Presentation Tier (Presentation Tier):

This layer constitutes the highest level of architecture the same purpose is to include the components which will be presented on screen(UI) and their respective precessors, in general you will use it as a bridge between the information that will be displayed and the content present in the other layers.

Any user interaction being input or output data should be allocated at this level of architecture.

Other Denominations: UI(User Interface) or VIEW

Logic Layer (Logic Tier):

Layer responsible for managing the logical processing of the application, this layer basically aims to aggregate all the complex processing of the application in order to ensure the oneness of responsibility on the business rules of the system or whatever is complex, require the merging of multiple entities, complex algorithms and data rules.

Some architects choose to centralize access to the layers of data in the business layers. Although redundant, there is a need to apply business rules in simple queries this redundancy removes the need for intervention in other layers later.

Other Denominations: BO(Business Object) or BLL(Business Logic Layer)

Data Layer (Data Tier):

Layer responsible for aggregating the persistence mechanisms, entities and methods responsible for providing access to the database, in this notorious layer is usually provided for each entity a class containing the methods of addition, deletion, listing and removal in addition to the specific queries that each entity may require.

Other Denominations: DAL(Data Access Layer), DAO(Data Access Object) or Repository

Summary:

Over the lifecycle of an application, the three-tier architecture provides many benefits, such as reusability, flexibility, management, maintenance, and scalability.

Gains from this type of implementation:

  • Reusability of components and distribution between different applications.
  • Possibility to divide large and complex projects into simpler projects and assign them to different teams or resources ensuring the uniqueness of the components of access to data and business rules.

Losses or problems with this type of implementation:

  • Productivity loss compared to monolithic development.
  • Increased data traffic if implemented in different machines.
  • Increased complexity in project implementation.

References:

  • 4

    I gave +1 in response for the effort, but it doesn’t answer exactly what DAO is. The answer talks a lot about layers and almost nothing about the Pattern design.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.