Skip to content

2 Persistencia

Introducción

La persistencia se refiere a la capacidad de almacenar y recuperar datos de forma duradera a través de diversas fuentes, como bases de datos, archivos, o incluso memoria, es decir, se trata de mantener la información más allá de la ejecución del programa para que pueda ser utilizada en sesiones posteriores o compartida entre diferentes aplicaciones.

La persistencia es una de las soluciones posibles al problema planteado en el proyecto anterior.

Patrón de diseño DAO

El patrón de diseño DAO (Data Access Object) es un patrón de diseño que se utiliza en programación para separar la lógica de acceso a datos de la lógica de negocio. Su objetivo principal es proporcionar una capa de abstracción entre la aplicación y la fuente de datos, lo que facilita la gestión de la base de datos y permite cambios en la base de datos sin afectar la lógica de la aplicación.

Este patrón tiene los siguientes componentes:

  • Interfaz DAO: Define los métodos que representan operaciones de acceso a datos, como insertar, actualizar, eliminar y recuperar datos. Esta interfaz sirve como contrato para las clases concretas que implementarán la lógica de acceso a datos.

    public interface StudentDAO {
        Student getById(int id);
        List<Student> getAll();
        void insert(Student student);
        void update(Student student);
        void delete(int id);
    }
    
  • Clase DAO: Implementa la interfaz DAO y proporciona la lógica real para interactuar con la fuente de datos, como una base de datos. Esta clase realiza operaciones de lectura y escritura en la fuente de datos, como consultas SQL en una base de datos relacional.

    public class StudentDAOImpl implements StudentDAO {
    // Implementación de los métodos definidos en la interfaz
    // Aquí se realizarían las operaciones de acceso a la base de datos.
    }
    
  • Modelo de datos (POJO): Representa los objetos de datos que se almacenan o recuperan de la fuente de datos. Los objetos de este tipo son simples y contienen propiedades que mapean a las columnas de la base de datos.

    public class Student {
        private int id;
        private String name;
        private int age;
        // Getters y setters
    }
    

De esta forma podemos realizar las operaciones de una base de datos de forma más sencilla:

public class Main {
    public static void main(String[] args) {
        // Crear una instancia del DAO
        StudentDAO studentDAO = new StudentDAOImpl();

        // Insertar un estudiante en la base de datos
        Student student = new Student();
        student.setName("John Doe");
        student.setAge(20);
        studentDAO.insert(student);

        // Recuperar un estudiante por ID
        Student retrievedStudent = studentDAO.getById(1);
        System.out.println("Nombre del estudiante: " + retrievedStudent.getName());

        // Actualizar un estudiante
        retrievedStudent.setName("Jane Smith");
        studentDAO.update(retrievedStudent);

        // Eliminar un estudiante
        studentDAO.delete(1);
    }
}

Implementación del patrón de diseño DAO al proyecto students

El primer cambio que sufre nuestro proyecto es la eliminación de la interfaz Source<T> por un interfaz especifica para cada tipo de dato:

public interface StudentDAO {
    Student getById(Integer id);
    List<Student> getAll();
    boolean save(Student student);
    boolean update(Student student);
    boolean delete(Student student);
}
public interface CourseDAO {
    Course getById(Integer id);
    List<Course> getAll();
    boolean save(Course course);
    boolean update(Course course);
    boolean delete(Course course);
}
public interface InscriptionDAO {
    Inscription getById(Integer id);
    List<Inscription> getAll();
    boolean save(Inscription inscription);
    boolean delete(Inscription inscription);
}

De esta forma tendremos una interfaz para cada modelo de datos, y así cada implementación realizará la misma operaciones, sin importar el tipo de fuente de datos que usemos.

Otro de los cambios a seguir, lógicamente, son nuestras clases lógicas, anteriormente llamadas Model, las cuales implementaban la interfaz Source y ahora implementarán las interfaces DAO que tenemos:

public class StudentDAOImpl implements StudentDAO {

    //...

    @Override
    public Student getById(Integer id) {
        // ...
    }

    @Override
    public List<Student> getAll() {
        // ...
    }

    @Override
    public boolean save(Student student) {
        //...
    }

    @Override
    public boolean update(Student student) {
       // ...
    }

    @Override
    public boolean delete(Student student) {
        //...
    }
}
public class CourseDAOImpl implements CourseDAO {
    //...

    @Override
    public Course getById(Integer id) {
       // ...
    }

    @Override
    public List<Course> getAll() {
        // ...
    }

    @Override
    public boolean save(Course Course) {
        // ...
    }

    @Override
    public boolean update(Course Course) {
        // ...
    }

    @Override
    public boolean delete(Course Course) {
        // ...
    }
}
public class InscriptionDAOImpl implements InscriptionDAO {
    //...
    @Override
    public Inscription getById(Integer id) {
        // ...
    }

    @Override
    public List<Inscription> getAll() {
        // ...
    }

    @Override
    public boolean save(Inscription inscription) {
        // ...
    }


    @Override
    public boolean delete(Inscription inscription) {
        // ...
    }
}

Patrón de diseño repository

El patrón de diseño Repository es un patrón de diseño de software que se utiliza para abstraer y centralizar la lógica de acceso a datos en una aplicación. Proporciona una interfaz común para acceder a datos, independientemente de la fuente de datos subyacente, como una base de datos, un servicio web o incluso una memoria caché. El patrón Repository también se utiliza para separar la lógica de acceso a datos de la lógica de negocio de una aplicación.

Los componentes de este patrón son:

  • Interfaz Repository: Define métodos para acceder a los datos, como guardar, recuperar, actualizar y eliminar objetos. Esta interfaz actúa como un contrato que las clases concretas deben implementar.

    public interface BookRepository {
        Book getById(int id);
        List<Book> getAll();
        void save(Book book);
        void update(Book book);
        void delete(int id);
    }
    
  • Clase Repository concreta: Implementa la interfaz Repository y proporciona la lógica de acceso a datos real. Puede interactuar con una base de datos, un servicio web, un sistema de archivos u otra fuente de datos.

    public class JdbcBookRepository implements BookRepository {
    // Implementación de los métodos definidos en la interfaz
    // Aquí se realizarían las operaciones de acceso a la base de datos.    
    }
    
  • Modelo de datos (POJO): Representa los objetos de datos que se almacenan o recuperan. Los objetos de este tipo son simples y contienen propiedades que mapean a los datos almacenados.

    public class Book {
        private int id;
        private String title;
        private String author;
    
        // Getters y setters
    }
    

DAO vs Repository

Aparentemente ambos patrones de diseño son bastantes parecido, pero aún así hay algunas diferencias entre ellos:

  1. Abstracción de la fuente de datos: En el patrón Repository, se busca proporcionar una capa de abstracción que abarque múltiples fuentes de datos, como bases de datos, servicios web, sistemas de archivos, etc. El patrón DAO generalmente se asocia más estrechamente con la interacción con bases de datos, aunque también puede utilizarse para otros tipos de fuentes de datos.

  2. Mapeo objeto-relacional: El patrón Repository a menudo incluye un mapeo objeto-relacional (ORM) para facilitar la conversión entre los objetos de la aplicación y los datos almacenados. En contraste, el patrón DAO tiende a tener una relación más directa con las consultas SQL o la interacción con la base de datos.

  3. Centralización de la lógica de acceso a datos: El patrón Repository se centra en centralizar la lógica de acceso a datos, mientras que el patrón DAO puede ser más flexible en términos de cómo se organiza la lógica de acceso a datos.

En resumen, el patrón Repository se centra en proporcionar una capa de abstracción más amplia para acceder a datos desde diversas fuentes, mientras que el patrón DAO se enfoca más específicamente en la lógica de acceso a datos en el contexto de una base de datos. La elección entre estos patrones dependerá de las necesidades y la arquitectura de tu aplicación.