domingo, 13 de octubre de 2019

DAO - Objeto de acceso a datos

Los DAO permiten mantener separado el acceso a los datos que pueden provenir de bases de datos, servicios web u otros de las demás tareas que realiza la aplicación, de esta forma las otras partes del programa no deben preocuparse del acceso a los datos, solamente de realizar sus tareas delegando al DAO las operaciones de consulta, inserción, modificación o eliminación de datos en la fuente de datos, que suele ser una base de datos.

DAO actúa como el nexo adaptador entre un componente (como un controlador o Servlet) y la fuente de datos (Como una base de datos SQLite)

Ventajas

Podemos encontrar un escenario actual donde los datos provienen de diversas fuentes como bases de datos relacionales, no relacionales, archivos, etc. y para cada uno de ellos existe una sintaxis diferente, si se cambiara de base de datos como de un Oracle a un PostgreSQL, la sintaxis del código SQL podría varias drásticamente y modificar las diversas partes de un programa que contengan estas sentencias sería costoso ytomaría mucho tiempo, pero si estas sentencias se encuentran localizadas en una sola área como el DAO, las modificaciones, pruebas e incluso la escalabilidad serías mucho más efectivas.

Los DAO abstraen y encapsulan los accesos a las fuentes de datos de forma que este maneja las conexiones con esa fuente, que podría ser por ejemplo una base de datos MySQL, para obtener los datos y almacenarlos posteriormente.

Usar DAO permite ocultar los procesos empleados en un programa que permiten acceder a la fuente de datos. Además, brinda un gran nivel de adaptación a diversas fuentes de almacenamiento sin afectar a las demás capas.

Nota: en los modelos MVC, MVP, MVVM, entre otros los DAO pertenecen a la capa del modelo (M)

Implementación en JAVA

Teniendo como apoyo un DTO o un OD (aunque no son necesarios, pero sí muy útiles) los DAO deben declarar primero una interfaz (esto dependerá mucho de la manera de implementar este patrón, pero usar interfaces tiene múltiples beneficios), para luego implementarse manteniendo un orden y mejorar la facilidad de emplear pruebas.

Ejemplo

Suponiendo la siguiente tabla y que le hemos creado un DTO (para ver como crear un DTO has clic aquí):
La interfaz "DaoInquilinos.java" se colocará dentro de un paquete llamado "dao", el código para dar un mantenimiento básico a la tabla "inquilinos" será

package dao;
import java.util.List;
import dto.Inquilinos;

public interface DaoInquilinos {
    public List <Inquilinos> inquilinosSel();
    public Inquilinos inquilinosGet(Integer id);
    public String inquilinosIns(Inquilinos inquilino);
    public String inquilinosUpd(Inquilinos inquilino);
    public String inquilinosDel(List<Integer> ids);
    public String getMessage();
}


Ahora debemos implementar cada una de esas funciones en un archivo llamado "DaoInquilinosImpl.java" que colocaremos en un paquete llamado "impl" dentro del paquete "dao", para ello empleamos la palabra reservada "implements" que indica que es la implementación del "DaoInquilinos". El código será:

package dao.impl;

import biblioteca.ConectaBD;
import dao.DaoInquilinos;
import dto.Inquilinos;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class DaoInquilinosImpl implements DaoInquilinos {

    private final ConectaBD conectaDb;
    private String mensaje;

    public DaoInquilinosImpl() {
        this.conectaDb = new ConectaBD();
    }

    @Override
    public List<Inquilinos> inquilinosSel() {
        List<Inquilinos> list = null;
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("idinquilinos,")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(" FROM inquilinos");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ResultSet rs = ps.executeQuery();
            list = new ArrayList<>();
            while (rs.next()) {
                Inquilinos inquilinos = new Inquilinos();
                inquilinos.setIdinquilinos(rs.getInt(1));
                inquilinos.setDni(rs.getString(2));
                inquilinos.setNombres(rs.getString(3));
                inquilinos.setPaterno(rs.getString(4));
                inquilinos.setMaterno(rs.getString(5));
                inquilinos.setTelefono(rs.getString(6));
                inquilinos.setCorreo(rs.getString(7));
                inquilinos.setDeuda(rs.getDouble(8));
                inquilinos.setFecha_ingreso(LocalDate.parse(rs.getString(9)));
                list.add(inquilinos);
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return list;
    }

    @Override
    public Inquilinos inquilinosGet(Integer id) {
        Inquilinos inquilino = new Inquilinos();
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ")
                .append("idinquilinos,")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(" FROM inquilinos WHERE idinquilinos = ?");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setInt(1, id);
            try (ResultSet rs = ps.executeQuery()) {
                if (rs.next()) {
                    inquilino.setIdinquilinos(rs.getInt(1));
                    inquilino.setDni(rs.getString(2));
                    inquilino.setNombres(rs.getString(3));
                    inquilino.setPaterno(rs.getString(4));
                    inquilino.setMaterno(rs.getString(5));
                    inquilino.setTelefono(rs.getString(6));
                    inquilino.setCorreo(rs.getString(7));
                    inquilino.setDeuda(rs.getDouble(8));
                    inquilino.setFecha_ingreso(LocalDate.parse(rs.getString(9)));
                } else {
                    inquilino = null;
                }
            } catch (SQLException e) {
                mensaje = e.getMessage();
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return inquilino;
    }

    @Override
    public String inquilinosIns(Inquilinos inquilino) {
        StringBuilder sql = new StringBuilder();
        sql.append("INSERT INTO inquilinos( ")
                .append("dni,")
                .append("nombres,")
                .append("paterno,")
                .append("materno,")
                .append("telefono,")
                .append("correo,")
                .append("deuda,")
                .append("fecha_ingreso")
                .append(") VALUES (?,?,?,?,?,?,?,?) ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setString(1, inquilino.getDni());
            ps.setString(2, inquilino.getNombres());
            ps.setString(3, inquilino.getPaterno());
            ps.setString(4, inquilino.getMaterno());
            ps.setString(5, inquilino.getTelefono());
            ps.setString(6, inquilino.getCorreo());
            ps.setDouble(7, inquilino.getDeuda());
            ps.setString(8, inquilino.getFecha_ingreso().toString());
            int ctos = ps.executeUpdate();
            if (ctos == 0) {
                mensaje = "cero filas insertadas";
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String inquilinosDel(List<Integer> ids) {
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM inquilinos WHERE ")
                .append("idinquilinos = ? ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            cn.setAutoCommit(false);
            boolean ok = true;
            for (int id = 0; id < ids.size(); id++) {
                ps.setInt(1, ids.get(id));
                int ctos = ps.executeUpdate();
                if (ctos == 0) {
                    ok = false;
                    mensaje = "ID: " + ids.get(id) + " no existe";
                }
            }
            if (ok) {
                cn.commit();
            } else {
                cn.rollback();
            }
            cn.setAutoCommit(true);
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String inquilinosUpd(Inquilinos inquilino) {
        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE inquilinos SET ")
                .append("dni = ?,")
                .append("nombres = ?,")
                .append("paterno = ?,")
                .append("materno = ?,")
                .append("telefono = ?,")
                .append("correo = ?,")
                .append("deuda = ?,")
                .append("fecha_ingreso = ? ")
                .append("WHERE idinquilinos = ? ");
        try (Connection cn = conectaDb.conexionDB()) {
            PreparedStatement ps = cn.prepareStatement(sql.toString());
            ps.setString(1, inquilino.getDni());
            ps.setString(2, inquilino.getNombres());
            ps.setString(3, inquilino.getPaterno());
            ps.setString(4, inquilino.getMaterno());
            ps.setString(5, inquilino.getTelefono());
            ps.setString(6, inquilino.getCorreo());
            ps.setDouble(7, inquilino.getDeuda());
            ps.setString(8, inquilino.getFecha_ingreso().toString());
            ps.setInt(9, inquilino.getIdinquilinos());
            int ctos = ps.executeUpdate();
            if (ctos == 0) {
                mensaje = "No se pudo actualizar";
            }
        } catch (SQLException e) {
            mensaje = e.getMessage();
        }
        return mensaje;
    }

    @Override
    public String getMessage() {
        return mensaje;
    }
}

Teniendo la siguiente estructura de carpetas para un proyecto de NetBeans:



No hay comentarios:

Publicar un comentario