Spring Vaadin Hibernate Tutorial > 5. DTOs, DAOs, Services y su implementación

Escrito por 6 mayo, 2016Desarrollo de software
Tutorial Spring Vaadin HIbernate, DTOs, DAOs, Services y su implementación

En este quinto paso del tutorial Spring Vaadin Hibernate nos centraremos en el módulo core, el cual contiene la lógica de nuestra aplicación. Para ello vamos a crear y definir los DAO y Services. Empecemos creando la siguiente estructura de directorios para albergar todas las clases que necesitamos:

DAO_Services

 

DAOs

A continuación necesitamos definir nuestros DAOs (Data Access Object). El papel principal de los DAO es la interacción de nuestro modelo con el acceso a datos. Por ello, en nuestros DAOs tendremos definidas las operaciones básicas de acceso, modificación, creación y actualización (CRUD) de nuestros datos. Cada DAO tendrá su interfaz (las interfaces nos indican qué se debe hacer, pero no cómo debe hacerse) y su implementación (se define el cómo).

Siempre que podamos intentaremos generalizar aquellos elementos que sean comunes, con el fin de añadir el menor código posible. Además del ahorro de tiempo que esto supone a la hora de realizar modificaciones. Es decir, definimos nuestra interfaz genérica, de la cual extenderán (heredarán) todos nuestros DAOs como se ve a continuación:

En esta interfaz definimos los métodos que serán comunes para todos nuestros DAOs. De esta manera toda clase que herede de cualquier interfaz, que a su vez herede de esta interfaz genérica, tendrá que implementar estos métodos.

Para que una interfaz extienda de esta interfaz genérica, la clase T debe extender de AbstractEntity. Siguiendo nuestro ejemplo, todas nuestras entidades creadas en el post anterior deben de heredar de esta clase. Vamos a usar de ejemplo la entidad Address, a la que tenemos que añadir esta extensión:

Ahora ya podemos definir su interfaz DAO correspondiente que hereda de la genérica anteriormente comentada:

En esta interfaz específica (IAddressDao) sólo incluiremos la declaración de los métodos que sean únicos para dicha entidad, ya que los métodos genéricos ya están definidos en la interfaz IPershopGenericDao. En este caso, para la entidad Address sólo necesitaremos adicionalmente dos métodos específicos: deleteById y findById.

Al indicar que IAddressDao extiende de IPetshopGenericDao <Address> estamos indicando que la clase genérica definida anteriormente, para el caso de IAddressDao, es la clase Address. Es decir:

es equivalente a:

Como indicamos en pasos anteriores, seguiremos siempre la buena práctica de generalizar todo lo que sea posible y por ello, crearemos la clase abstracta AbstractPetshopGenericDao. Esta clase abstracta debe ser genérica y nos proveerá de muchos de los métodos de acceso a datos (como save, delete, insert…), a través de la implementación que hace JPA (Java Persistence API) con GenericDaoJpaImpl. Entonces, la declaración de nuestra clase abstracta quedará de la siguiente forma:

Llegados a este punto, debería llamarnos la atención este EntityManager con su anotación  @PersistenceContext.

Persistence Context

Nos indica el contexto de persistencia de nuestros objetos. ¿Qué quiere decir esto? es el encargado de automatizar la persistencia (modificación, acceso, creación y borrado – CRUD –) de nuestros objetos en base de datos. Para que esto sea posible es necesario crear y configurar el archivo persistence.xml:

persistence

 

Este archivo con formato xml es el encargado de conectarnos con nuestra base de datos e indicar qué entidades son las que vamos a gestionar (persistir):

Como podemos observar en nuestro ejemplo, nuestra unidad de persistencia es PetshopUnitpor ello en la clase abstracta añadíamos la anotación:

Por otro lado, en este fichero le indicamos que para PetshopUnit las clases a persistir son las que están definidas con la etiqueta <class>. Mientras que para la conexión a nuestra base de datos se realizará con los parámetros definidos en <properties>.

El EntityManager es el encargado del acceso a base de datos, es decir, que todas las operaciones relacionadas con las operaciones CRUD en base de datos se realizarán a través de él.

Implementación de los DAO

Para tener un ejemplo de cómo implementar uno de nuestros DAOs, continuaremos con el ejemplo de la entidad Address y crearemos la clase AddressDaoImpl. Esta clase es la que implementa los métodos definidos en nuestra interfaz IAddressDao.

Esto es sólo un ejemplo de la implementación de algunos métodos que deben de ser implementados por esta clase. Faltarían todos los demás métodos que hemos definido en IAddressDao y en IPetshopGenericDao:

Como podemos observar, utilizamos el EntityManager definido anteriormente para realizar las consultas a base de datos. Diferentes ejemplos de consultas pueden encontrarse en   http://docs.oracle.com/javaee/6/tutorial/doc/bnbrg.html.

En resumen, nuestra estructura de ficheros seguirá el siguiente esquema:

DaoImpl

 

Services y su implementación

Llegamos por fin a los Services, que son los encargados de consumir (hacer uso) todo lo que hemos implementado hasta ahora.

¿Por qué hemos creado todas estas capas antes de llegar a este punto? Podíamos haber definido en el mismo lugar tanto el acceso a base de datos, como toda la lógica de nuestra aplicación, pero no seguiríamos la buena práctica de aislar todo lo que sea posible, de encapsular cada capa. Al hacer esto, tenemos la posibilidad de cambiar cualquier capa de nuestra aplicación sin que la capa superior o inferior se vean afectadas (o los cambios fueran mínimos). Por ejemplo, imaginemos que para la capa de persistencia aparece un framework que nos realiza todas las operaciones de acceso de datos sin tener que realizar nosotros ninguna configuración. Sólo necesitaríamos modificar el módulo persistence, haciendo uso de ese framework de manera trasparente para el resto del proyecto.

A grandes rasgos, se entiende que los DAO sólo deben preocuparse del acceso a base de datos, quedando toda la lógica de la aplicación en los Services.

En nuestro ejemplo, la estructura de los ficheros a crear es la siguiente:

services

 

DTOs

Los DTO son clases que sirven para transferir los datos obtenidos de la base de datos. Su finalidad es adaptar (acotar o ampliar) el conjunto de datos a transferir. Por ejemplo, no tendría sentido que una tabla en la que tenemos decenas de columnas, sean todas ellas accesibles desde la capa de servicios. Por el contrario, tiene mucha más lógica que solamente utilicemos aquellas columnas que sean relevantes desde nuestra capa de servicios. Es decir, los Services hacen uso de los DTOs para todas sus operaciones.

Y de nuevo aparece nuestra clase genérica, la cual intenta generalizar algún comportamiento. En este caso obligaremos a todas las clases que hereden de este AbstractDTO a que implementen el método toEntity:

Por cada entidad tendremos nuestro DTO correspondiente. Además de implementar el método toEntity definido en AbstractDTO, todos ellos tendrán una estructura parecida (según los datos que se requieran para sus servicios) a la siguiente:

Ejemplo de Service

Vamos a ver un ejemplo de service, IAddressService:

Y la implementación de estos métodos, en ServiceAddressImpl:

Nos debe de llamar la atención la anotación @Autowired, la cual le indica a Spring que nos instancie la interfaz IAddressDao (dado que sólo tendremos una implementación de nuestra interfaz IAddressDao, Spring no tendrá problemas para encontrar esta implementación). De esta manera, ahora podremos hacer uso de los métodos que nos provee esta interfaz. Por ejemplo, nuestro método findAllAddress realizará una llamada al método findAll (que se encuentra definido en IAddressDao e implementado en AddressDaoImpl), el cual es el encargado de realizar la petición a la base de datos.

Al finalizar este post ya tenemos la base de nuestra aplicación, todo el código se puede ver en GitHub. Le hemos ido dando forma desde simplemente una estructura de datos de una base de datos existente hasta tener los servicios que nos permitirán hacer las operaciones CRUD (Create, Read, Update and Delete) en la misma.

Join the discussion Un comentario

Dejar un comentario

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies.

ACEPTAR
Aviso de cookies