Sunteți pe pagina 1din 23

Framework Spring, MVC y DAO - Diseño de Sistemas

Autor: Ignacio Paz Versión : 1.01 [27/02/18]


Cátedra Diseño de Sistemas UTN – F.R.Ro.

Framework Spring, MVC y DAO


Diseño de Sistemas
1. Índice
1. Índice ............................................................................................................................................................ 1
2. Introducción .................................................................................................................................................. 3
2.1. Propósito del documento ...................................................................................................................... 3
2.2. Alcance del documento ......................................................................................................................... 3
2.3. Documentos Relacionados ................................................................................................................... 3
2.4. Visión general del documento ............................................................................................................... 3
3. Enfoque de arquitectura para soluciones de Diseño de Sistemas .............................................................. 4
4. Conceptos y principios para soluciones de diseño ...................................................................................... 4
4.1. ¿Qué es una interfaz? ........................................................................................................................... 4
5. Framework de desarrollo Spring .................................................................................................................. 5
5.1. ¿Qué es un framework de desarrollo? .................................................................................................. 5
5.2. Framework Spring ................................................................................................................................. 5
6. Patrón MVC (Modelo vista controlador) ....................................................................................................... 7
6.1. Patrón MVC en Spring Web MVC ......................................................................................................... 8
7. Dominio ........................................................................................................................................................ 9
7.1. Controlador y dominio ........................................................................................................................... 9
7.2. Dominio, mapeo y persistencia ............................................................................................................. 9
7.2.1. Persistencia ................................................................................................................................... 9
7.2.2. Mapeo Objeto-relacional .............................................................................................................. 10
7.2.3. Framework de persistencia Objeto-relacional ............................................................................. 10
7.3. Características de los objetos del dominio ......................................................................................... 10
8. DAO (Data Access Object) o repositorios .................................................................................................. 10
8.1. Patrón DAO y persistencia en Spring ................................................................................................. 11
8.1.1. Interfaz JpaRepository ................................................................................................................. 11
8.1.2. Anotaciones y configuración de persistencia............................................................................... 12
8.1.2.1. Anotación @Entity ................................................................................................................ 12
8.1.2.2. Anotación @Id ...................................................................................................................... 12
8.1.2.3. Anotación @GeneratedValue ............................................................................................... 13
8.1.3. Como se crean las instancias de los DAO .................................................................................. 13
8.2. Lenguaje de Consultas JPQL ............................................................................................................. 14
8.2.1. Estructura de Consulta ................................................................................................................ 14
8.2.2. Ejemplos de consultas JPQL ....................................................................................................... 14
8.2.3. Dao y consultas JPQL ................................................................................................................. 15
8.2.4. La cláusula FROM ....................................................................................................................... 15
8.2.4.1. Inner Joins ............................................................................................................................ 15
8.2.4.2. Left Outer Joins .................................................................................................................... 16
8.2.4.3. Condiciones adicionales para Join ....................................................................................... 16
8.2.4.4. Joins Implícitos ..................................................................................................................... 16
8.2.5. Proyección: La cláusula SELECT ................................................................................................ 16
8.2.5.1. Entidad .................................................................................................................................. 17
8.2.5.2. Distinct .................................................................................................................................. 17
8.2.6. Restricción: La cláusula WHERE ................................................................................................ 17
8.2.6.1. Operadores para valores simples......................................................................................... 17
8.2.6.2. Operadores para colecciones ............................................................................................... 18
8.2.7. Funciones .................................................................................................................................... 18
8.2.8. Agrupamiento: La cláusula GROUP BY y HAVING .................................................................... 19
8.2.9. Ordenamiento: La cláusula ORDER BY ...................................................................................... 19
8.2.10. Sub-consultas ........................................................................................................................... 19
8.2.11. Polimorfismo............................................................................................................................. 20
8.2.12. Ejercicios de consultas JPQL ................................................................................................... 21
8.2.12.1. Verificar consultas del apunte .............................................................................................. 21
9. Apéndice..................................................................................................................................................... 21
9.1. Principios SOLID ................................................................................................................................. 21

1/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

9.1.1. Single responsibility principle ....................................................................................................... 21


9.1.2. Open/closed ................................................................................................................................. 21
9.1.3. Liskov substitution principle ......................................................................................................... 21
9.1.4. Interface segregation principle ..................................................................................................... 22
9.1.5. Dependency inversion principle ................................................................................................... 22
9.2. Ejemplo de uso de interfaces, implementaciones y principios SOLID ............................................... 22
9.3. Ejercicio ............................................................................................................................................... 23
10. Bibliografía .............................................................................................................................................. 23
11. Historia de Versiones del documento ..................................................................................................... 23

2/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

2. Introducción
2.1. Propósito del documento
Especificar los artefactos de arquitectura para construir los diagramas de secuencia de diseño y los
diagramas de clase de diseño en la asignatura Diseño de Sistemas.

2.2. Alcance del documento


Las consignas de este documento aplican a todos los alumnos de la asignatura Diseño de Sistemas
de la carrera de Ingeniería en Sistemas de Información dictada en la Universidad Tecnológica Nacional -
Facultad Regional Rosario.

2.3. Documentos Relacionados


Documento Nombre / Ubicación del archivo Fuente
Mapeo O/R
Libro larman

2.4. Visión general del documento


Proveer conceptos y convenciones de arquitectura y del framework Spring con el objetivo de
utilizarlos para las soluciones de los diagramas de Diseño de Sistemas.

3/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

3. Enfoque de arquitectura para soluciones de Diseño de


Sistemas
Si bien hay muchas variantes y enfoques posibles para la arquitectura de una aplicación. Para las
soluciones de diseño vamos a asumir un enfoque de arquitectura clásico con las siguientes características:
• Ambiente Web.
• Basado en el patrón MVC.
• Uso del modelo de dominio rico en comportamiento.
• Patrón DAO o Repositorio para el acceso a datos.
• Persistencia en base de datos relacional.
• Uso del Framework de desarrollo Spring.
• Desarrollado con el Lenguaje de programación Java.

Este enfoque de arquitectura ayude a entender cualquier otro enfoque de arquitectura de cualquier
aplicación, aunque se debe entender que según la tecnología o frameworks que se utilice puede cambiar
bastante.

4. Conceptos y principios para soluciones de diseño


4.1. ¿Qué es una interfaz?
Una interfaz en Java es una colección de métodos abstractos y propiedades constantes. En las
interfaces se especifica qué se debe hacer, pero no su implementación. Serán las clases que implementen
estas interfaces las que describan la lógica del comportamiento de los métodos. Permite definir un
comportamiento de la forma más abstracta posible permitiendo diferentes implementaciones. De esta forma
las clases generan una dependencia con la interfaz sin saber de qué clase es el objeto con el que interactúan
permitiendo usar cualquier implementación y variantes.
Características:
• Definen comportamiento abstracto sin implementación. Definen un contrato que tiene que ser
implementado.
• La principal diferencia entre una interfaz y una clase abstracta es que una interfaz proporciona un
mecanismo de encapsulación de los protocolos de los métodos sin forzar al usuario a utilizar la
herencia.
• Tanto la interfaz como la clase abstracta no se pueden instanciar. La clase abstracta permite
tanto métodos abstractos como métodos concretos, mientras que la interfaz sólo permite
métodos abstractos.
• Una clase no hereda de una interfaz, sino que “implementa” la interfaz.
• Cuando una clase “implementa” una interfaz está obligada a implementar todos los métodos de la
interfaz, a menos que sea una clase abstracta.
• Una interfaz puede ser implementada por muchas clases.
• Una clase puede “implementar” muchas interfaces, mientras que sólo puede heredar de una sola
clase.
• Una interfaz no puede implementar ni extender una clase ya que está en el nivel de abstracción
más alto.
• Una interfaz puede heredar una o muchas interfaces. La interfaz no implementa otras interfaces
ya que sigue siendo 100% abstracta.
• A diferencia de la herencia entre clases, dos clases que implementan una interfaz no son
subclases de la interfaz ni están dentro de una jerarquía de clases. Son dos clases no
relacionadas que implementan el mismo contrato.
Para ver un ejemplo de interfaz sugerimos revisar los principios SOLID.

4/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

5. Framework de desarrollo Spring


5.1. ¿Qué es un framework de desarrollo?
Un framework (marco de trabajo) es un conjunto estandarizado de conceptos, prácticas y criterios
para enfocar un tipo de problemática particular que sirve como referencia, para enfrentar y resolver nuevos
problemas de índole similar.

En el desarrollo de software, un framework es una estructura conceptual y tecnológica de asistencia


definida, normalmente, con artefactos o módulos concretos de software, que puede servir de base para la
organización y desarrollo de software. Típicamente, puede incluir soporte de programas, bibliotecas, y un
lenguaje interpretado, entre otras herramientas, para así ayudar a desarrollar y unir los diferentes
componentes de un proyecto.

Un framework no es un lenguaje de programación, sino que se construye con un determinado


lenguaje de programación y proveen una solución particular a resolver problemas técnicos e implementación
de patrones de diseño o de arquitectura, por ejemplo. Para cualquier lenguaje de programación y
problemática a resolver, generalmente existen muchos frameworks que se pueden usar.
Algunos de los frameworks de desarrollo más utilizados:
• AngularJs (Javascript)
• ReactJs (Javascript)
• Node.Js (Javascript)
• Spring (Java)
• jHipster (Java)
• Play Framework (Java)
• GWT (Java)
• Struts 2 (Java)
• Grails (Groovy)
• ASP.Net (.Net)
• Laravel (PHP)
• Cake PHP (PHP)
• Symfony (PHP)
• Ruby on rails (Ruby)
• Django (Python)

Dicho de otra forma, un framework de desarrollo suele ser un esqueleto reusable de arquitectura o
aplicación base genérica en un lenguaje dado que permite utilizarse en muchas variantes de negocio. De
esta forma los desarrolladores no se preocupan por cómo resolver esos problemas técnicos o
arquitectónicos, sino que se enfocan más en los problemas de lógica del negocio de la aplicación que están
construyendo.
No es necesario ni requerido utilizar un framework para construir una aplicación, pero casi siempre
se usa uno ya que son construidos con calidad, han sido probados al construir miles de aplicaciones y han
ido evolucionando a lo largo de mucha experiencia y años de trabajo.

5.2. Framework Spring


El framework Spring provee un amplio modelo de programación y configuración para construir
aplicaciones empresariales modernas en Java y que puedan ser desplegadas en cualquier tipo de
plataforma. Spring se focaliza en la estructura base e infraestructura de la aplicación para que los equipos de
desarrolladores se puedan focalizar a nivel de la lógica de negocio de la aplicación sin atarse a ningún tipo de
entorno de despliegue específico.

Características del framework Spring:


• Inyección de dependencias.
• Promueve la dependencia por interfaces y no por clases.
• Programación orientada a aspectos.
• Frameworks Spring MVC (modelo-vista-controlador) y Spring WebFlux (programación reactiva) web.
• Facilidades para crear Repositorios y Dao.

5/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

• Soporte para bases de datos NoSQL.


• Incluye integración con otros frameworks y plataformas.
• Cada componente o sub framework que trae se puede usar por separado.
• Se adhiere a estándares e interfaces de java.
• Muchos más.

6/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

Nota: Como se ve el framework spring tiene muchos modulos, librerías y frameworks por lo que permite
muchas variantes de cómo utilizarlo y combinar estos módulos.
A los efectos de cumplir con el enfoque de arquitectura para soluciones de Diseño de Sistemas, en el resto
del documento nos vamos focalizar en uso simple y práctico de este framework teniendo en cuenta solo los
componentes más utilizados.

6. Patrón MVC (Modelo vista controlador)


El patrón de arquitectura MVC (Model view controller) es un enfoque clásico para construir
aplicaciones separando los intereses y responsabilidades de cada objeto que interviene.

Flujo de MVC en la web:

3) consulta o modifica el
2) Recibe Controlador modelo
1) Ingresa URL Solicitud
http://mydomain.com/about
/
4) carga la vista Modelo
adecuada para esta
solicitud y le pasa los
6) Respuesta datos u objetos mínimos
a la solicitud del modelo que la vista
necesita mostrar.

5) Consulta los datos del


Vista modelo que hay que
mostrar en la respuesta

Controlador: Recibe solicitudes de trabajo y las procesa para lograr la respuesta adecuada.
• No debe resolver lógica de negocio ni hacer cálculos.
• Delega toda la responsabilidad de la lógica del negocio a los objetos del modelo.
• Delega toda la responsabilidad de presentación de datos y usabilidad a la vista.
• Es responsable de resolver lo haga falta de un caso de uso haciendo lo mínimo posible y delegando
al máximo a los objetos del modelo (por ejemplo Dao y Dominio) y la vista.
• En base a condiciones decide cual es la vista que se debe cargar y controla como y hacia donde
continúa el flujo de la aplicación.
• Carga la vista que corresponde para la respuesta y le pasa los datos u objetos del modelo que
necesita.
• Dentro de una aplicación, no hay un único controlador, sino que hay muchos. Si bien no hay una
regla y depende del diseño, es común que haya un controlador por cada caso de uso o historia de
usuario.
• De un mismo controlador pueden existir muchas instancias funcionando para atender muchos
usuarios del mismo caso de uso al mismo tiempo.
Modelo: Conjunto de objetos que resuelven la lógica del negocio y el dominio.
• Incluye clases de dominio con métodos del negocio.
• Incluye clases de software como Repositorios o DAOs (Data Access object) para conexión a bases
de datos y clases de Servicio.
• Suele haber varias capas dentro del modelo.
• No resuelve nada ligado a la presentación de datos al usuario.
Vista: Componentes responsables de generar el contenido que se va a mostrar al usuario final (ejemplo:
HTML).
• No debe resolver lógica de negocio ni hacer cálculos.
• Recibe los datos u objetos del modelo que necesita consultar para mostrar al usuario.

7/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

• Resuelven toda la lógica ligada a la presentación e interfaz de usuario como ocultar, mostrar una
imagen, bloquear, habitar un textbox, cambiar el título de un Label, validar que un campo es
requerido, cambiar un color según la acción de un usuario, bloquear o habilitar un botón, etc.
• Según las acciones del usuario como hacer clic en un botón, pueden realizar una nueva solicitud al
controlador.

6.1. Patrón MVC en Spring Web MVC


Spring provee una implementación del patrón de arquitectura MVC (Model view controller) para
entorno web.
Spring utiliza el partón front controller como componente principal para procesar las solicitudes al
servidor.
A continuación, se describe el flujo de procesamiento típico para una petición HTTP en Spring MVC.
Esta explicación está simplificada y no tiene en cuenta ciertos elementos que comentaremos posteriormente.
Spring es una implementación del patrón de diseño "front controller", que también implementan otros
frameworks MVC, como por ejemplo, el clásico Struts.

3) Maneja y resuelve el
pedido interactuando
2) Según el URL, invoca a con otros objetos
un método específico de como repositorios,
un controlador. Cada DAO y objetos del
método de cada dominio y servicios.
controlador tiene
definido a que URL
1) Solicitud por URL procesa. Controlador
Front Controller
10) Respuesta (componente Controlador 1 Controlador 2 4) Crea un
HTML provisto por Spring) model, vista met1(p) met1(p) objeto
met2(p) met2(p)
“model” solo
Controlador 3 con los datos
6) Delega como se 5) Retorna el met1(p)
9) Retorna va a mostrar la u objetos del
model y el met2(p)
el control model vista. dominio que
nombre
y la vista necesita la
de la vista
procesad vista.
7) Carga la vista que se
a como debe
que indicó el
HTML.
controlador y lo cargar.
procesa con los
objetos que Modelo
Vista están dentro de
model.
vista 1 Dominio DAO
vista 2 BD
8) Consulta los datos
del model que
recibió que necesita
para la presentación.

Componente a ser desarrollado

8/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

Todas las peticiones HTTP se canalizan a través del front controller. En casi todos los frameworks
MVC que siguen este patrón, el front controller no es más que un servlet de java cuya implementación es
propia del framework. En el caso de Spring, la clase DispatcherServlet.
El front controller averigua, normalmente a partir de la URL, a qué Controller hay que llamar para
servir la petición. Para esto se usa un HandlerMapping que no aparece en el diagrama.
Se llama al Controller, que ejecuta la lógica de negocio, obtiene los resultados y los devuelve al
servlet, encapsulados en un objeto del tipo Model. Además se devolverá el nombre lógico de la vista a
mostrar (normalmente devolviendo un String, como en JSF).
Un ViewResolver (no aparece en el diagrama) se encarga de averiguar el nombre físico de la vista
que se corresponde con el nombre lógico del paso anterior.
Finalmente, el front controller (el DispatcherServlet) redirige la petición hacia la vista, que muestra los
resultados de la operación realizada.
En realidad, el procesamiento es más complejo. Nos hemos saltado algunos pasos por simplicidad y
para dar una mayor claridad. Por ejemplo, en Spring se pueden usar interceptores, que son como los filtros
del API de servlets, pero adaptados a Spring MVC. Estos interceptores pueden pre y postprocesar la petición
alrededor de la ejecución del Controller. No obstante, todas estas cuestiones deben quedar por fuerza fuera
de una breve introducción a Spring MVC como la de estas páginas.

Desde el punto de vista del desarrollador, sólo se debe preocupar por implementar los controladores,
vista y objetos del modelo ya que los demás componentes son provistos por Spring para el funcionamiento
del MVC.

En la parte de Modelo de MVC hemos incluido los objetos del Dominio y clases de software llamadas
DAO (Data Access Object) que encapsulan el acceso a la base de datos. Este es un enfoque de arquitectura,
pero no el único y se puede resolver de otras maneras.
Tampoco es requerido que el Controlador las utilice, pero es lo más común. A veces también se
incluyen algunas otras clases como servicios para reutilizar lógica entre varios controladores.
Para simplificar la arquitectura vamos asumir que el Controlador va a interactuar con los DAO y
objetos del dominio directamente.

7. Dominio
En el dominio están las clases de negocio. Estas clases resuelven la mayor parte de lógica de
negocio y tienen responsabilidades de negocio bien definidas y de única responsabilidad.

7.1. Controlador y dominio


El controlador va a delegar la mayor cantidad de responsabilidades del negocio a las clases del
dominio y se limitará lo máximo posible a coordinar las actividades entre estos para cumplir con el objetivo
del caso de uso.

7.2. Dominio, mapeo y persistencia

7.2.1. Persistencia
Todos los objetos de cualquier clase deben estar en memoria RAM para poder ejecutarse, sin
embargo, casi todos los objetos del dominio además son persistentes, esto quiere decir que las instancias de
una clase de dominio se deben guardar en un medio físico para que puedan ser recuperadas más adelante
en cualquier momento más allá de la vida o ejecución de la aplicación (por ejemplo, luego de que la
aplicación o servidor se reinicia) ya que representan la información que el negocio genera y/o necesita para
funcionar. En nuestro caso vamos a asumir que las instancias van a ser guardadas como registros de alguna
tabla en una base de datos. A su vez cuando se desee cargar una instancia de una clase de dominio se debe
leer el registro correspondiente de la tabla de la base de datos y cargarla en memoria como un objeto.
Otras clases como el Controlador y DAO no necesitan ser persistentes.
Los objetos del dominio no son responsables de la persistencia. Dicho de otra forma, no saben que
son persistidos ni que existe la persistencia. Para eso se aplica el patrón DAO para resolver la persistencia
de esos objetos sin que se enteren. A su vez los objetos del dominio no invocan métodos a los DAO ni saben
de su existencia. Los objetos del dominio tampoco saben de la existencia de otros objetos del dominio a
menos que tengan una asociación con estos, instancien algunos o se los pasen como referencia.

9/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

7.2.2. Mapeo Objeto-relacional


El mapeo objeto relacional se refiere a la estrategia de como las clases persistentes se deben
representar en un modelo relacional y el mecanismo para transformar registros en instancias y vice versa.
Existen varias estrategias de mapeo, aunque lo más común es que por cada clase de dominio haya
una tabla, por cada atributo de la clase haya un campo en esa tabla y por cada instancia de la clase haya un
registro en dicha tabla.

7.2.3. Framework de persistencia Objeto-relacional


Si bien el mecanismo de leer un registro para convertirlo en un objeto o viceversa puede parecer
fácil, no lo es. Se presentan muchas complejidades y casos que harían muy costoso y poco efectivo que un
desarrollador cree este mecanismo desde cero.
Por eso se suelen utilizar frameworks de persistencia como Hibernate, nHibernate, ibatis, eclipseLink,
JPA.

7.3. Características de los objetos del dominio


• Casi siempre son persistentes.
• No son responsables de la persistencia.
• No saben que son persistidos ni que existe la persistencia.
• No saben de la existencia de los DAO y de los controladores y nunca acceden a ellos.
• No saben de la existencia de otros objetos del dominio a menos que los conozcan a través de
una asociación con estos, instancien objetos o se los pasen como referencia en un método.
• Son ricos en comportamiento y resuelven lógica del negocio. No son contenedores de datos.
Su valor está en sus métodos y no en sus atributos.
• Son capaces de resolver todo lo que puedan en base a lo que conocen de sus atributos y
todos los objetos que conocen a través de sus asociaciones.

8. DAO (Data Access Object) o repositorios


Un DAO (o repositorio) es un patrón de arquitectura para resolver el problema de acceso a datos de
una aplicación. En el contexto más común donde las clases de dominio deben ser persistentes, el DAO
encapsula como se realiza la persistencia de estos objetos del dominio a una base de datos. De esta forma
permite que la lógica de encontrar o guardar objetos de determinado tipo pueda ser reutilizado por muchos
controladores.
Un DAO debe tener las siguientes características:
• En general, existe un DAO por cada clase del dominio que sea persistente. Por ejemplo, si
existe una clase Venta, existirá un VentaDAO.
• En el caso que dos objetos de dominio tengan una composición o relación todo-parte puede
ser que sólo haya un DAO para la clase que representa el todo. Por ejemplo, para las clases
Venta y LineaVenta, sólo hará falta un VentaDAO. Sería raro que se use un LineaVentaDAO,
a menos que haya una necesidad especial de hacer búsquedas sobre los objetos
LineaVenta.
• Es responsable de guardar o retornar objetos de un determinado tipo. Por ejemplo, un
ProductoDAO será responsable de buscar y guardar objetos de tipo Producto.
• Un DAO retorna o guarda sólo los objetos que representa. Por ejemplo, un ProductoDAO
sólo guarda o retorna objetos de tipo Producto, pero no puede retornar o guardar objetos de
tipo Venta, Cliente, String, Integer, etc.
• Un DAO retorna objetos de dominio de determinado tipo, pero nunca datos de esos objetos.
Por ejemplo, un ProductoDAO puede retornar uno o muchos objetos de tipo Producto, pero
nunca retornará datos de esos objetos como un array con el idProducto, nombreProducto y
precio. Será responsabilidad del controlador o la UI obtener el precio o nombreProducto
desde el objeto de tipo Producto para los objetivos del caso de uso. El DAO resuelve como
obtener esos objetos de una clase del dominio desde la base de datos, pero no es su
problema o responsabilidad saber para que se van a usar o para que caso de uso.
• Son altamente cohesivos y con bajo acoplamiento. Se enfocan en resolver un problema de
persistencia para una sola clase del dominio.

10/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

8.1. Patrón DAO y persistencia en Spring


Spring provee varias facilidades para hacer fácil la implementación de los DAO y la persistencia de
los objetos del dominio utilizando JPA (Java persistence API).
Spring promueve la dependencia por interfaces y el mecanismo de inyección de dependencia como
buena práctica. En las siguientes secciones haremos algunas simplificaciones para efectos educativos de la
cátedra.

8.1.1. Interfaz JpaRepository


Para crear un DAO (o repositorio) se debe crear una interfaz que extienda (herede) la interfaz
genérica JpaRepository.
La interfaz genérica JpaRepository es provista por el framework Spring como plantilla para cualquier
DAO de una clase del dominio persistente y ya trae una serie de métodos que se utilizan siempre en los
todos los DAO. De esta forma Spring nos regala la implementación de nuestra DAO con los métodos más
comunes y en el caso que necesitemos consultas específicas podemos escribir las llamadas consultas JPQL
en un lenguaje de consultas similar al SQL pero pensado para la orientación a objetos y referenciando clases
en vez de tablas y atributos en vez de campos.
La interfaz JpaRepository<T,ID> es “genérica”, esto quiere decir que su definición va a utilizar
algunas clases cuyos tipos de dato no están definidos o son “genéricos” y para eso tiene algunos parámetros
que serían como huecos para que al extender o implementar la interfaz se especifique de qué tipo de dato
serán.
Los parámetros de JpaRepository son:
• Parámetro T para especificar la clase del dominio persistente que este DAO va a manajear.
• Parámetro ID para especificar el tipo de dato del id o clave primaria de la clase T.

Las clases Cliente y Localidad son clases persistentes del dominio. Por ejemplo para crear un DAO
para la clase de dominio Cliente, tenemos que crear una interfaz ClienteDao que herede de la interfaz
JpaRepositroy. T e ID son tipos de datos no definidos en JpaRepository. Al extender la interfaz JpaRepository
se debe definir que T va a ser de la clase Cliente y que ID va a ser de tipo Integer.

11/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

Ahora cuando usemos un ClienteDao este tendrá todos los métodos de JpaRepository (pero reemplazando T
por Cliente e ID por Integer) mas los métodos específicos para buscar clientes que uno le quiera agregar a
ClienteDao.
Es decir que una instancia de ClienteDao será capaz responder a métodos como:
Método descripción
buscarClientesPorLocalidad(l:Localidad) Método adicional que agrega ClienteDao. Hay
que definir una anotación con una consulta JPQL:
SELECT c FROM Cliente c where c.localidad =
?1
buscarClientesPorNombre(nombre:String) Método adicional que agrega ClienteDao. Hay
que definir una anotación con una consulta JPQL:
SELECT c FROM Cliente c where c.nombre like
?1
getOne(id:Integer):Cliente devuelve una instancia de Cliente según su id
findAll():Cliente[*] devuelve una colección con todas las instancias
que existan de clientes.
save(c:Cliente) guarda el objeto c:Cliente en la base de datos. Si
no existe lo inserta, si ya existe lo actualiza.
existsById(id:Integer) :Boolean Devuelve true si existe un Cliente con ese id.
count():Integer Devuleve la cantidad de objetos de ese tipo que
existen guardados.
delete(c:Cliente) Elimina ese cliente de la base de datos.
deleteAll() Elimina todos los objetos cliente.
deleteById(id:Integer) Elimina un cliente con ese id de la base de datos.
saveAll(entidades:Cliente[*]) Guarda todos los clientes de una colección en la
base de datos.

8.1.2. Anotaciones y configuración de persistencia


Además de crear el DAO debemos configurar la base de datos y hacer algunas anotaciones en la
clase en las clases de dominio para que el framework Spring sepa cómo se van a persistir y cómo será el
mapeo a las tablas.
Para la necesidad de la materia lo vamos a simplificar y solo marcar algunas anotaciones.
Simplificando mucho, podemos decir que una anotación es como un comentario pero que además
tiene cierta sintaxis y semántica obligatoria y es validada por el compilador.

8.1.2.1. Anotación @Entity


Las clases que sean persistentes deben tener la anotación @Entity. Por eso se suele referir a las clases
persistentes como “entidades”. En UML vamos a omitir el uso de esta anotación.

8.1.2.2. Anotación @Id


Requerida para todas las clases de dominio que tengan un Dao. Debemos marcar con @Id al atributo
de la Clase de dominio que es la clave primaria. El tipo de dato debe coincidir con el que definimos en el
parámetro genérico ID del DAO. Por ejemplo en la clase Cliente tenemos el atributo idCliente:Integer {@Id } y
en ClienteDao definimos que ID-> Integer.

12/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

8.1.2.3. Anotación @GeneratedValue


En caso que debamos crear instancias de Cliente o la clase de dominio que tendrá un Dao y
debamos guardarlas con el método save(c:Cliente) y queremos que el valor de idCliente se genere
automáticamente por la base de datos o motor de persistencia cuando se guarda por primera vez, también
debemos marcar el atributo con la anotación @GeneratedValue. De no hacerlo, deberíamos definir nosotros
manualmente el valor del IdCliente que queremos que se guarde o el método save tirará un error.

8.1.3. Como se crean las instancias de los DAO


¿Cómo se crean las instancias si el JpaRepository y el ClienteDao son interfaces y no están
implementadas por ninguna clase? Bueno, acá entra en juego la practicidad de usar un framework, en este
caso el framework spring se encarga de generar una implementación dinámicamente que es invisible a los
ojos del desarrollador. Spring genera una implementación del Dao y utiliza la inyección de dependencias para
inyectarla en los objetos que la desean usar.

En este caso el ControladorAltaCliente tiene una asociación con ClienteDao y tiene un atributo
cdao:ClienteDao.
Cuando Spring se ejecuta lee las clases existentes y sus anotaciones y sabe que tiene que crear una
implementación de ClienteDao para la clase Cliente que tiene un Id de tipo Integer en el atributo idCliente y lo
inyecta en la variable cdao del ControladorAltaCliente. Además la implementación que crea Spring sabe que
cuando se ejecute un método como buscarClientesPorLocalidad(l:Localidad) deberá ejecutar la consulta
JPQL: SELECT c FROM Cliente c where c.localidad = ?1. O sea, que el Controlador nunca sabe cuál es la
implementación real sino que sabe que utiliza algo de tipo ClienteDao y responde a los métodos que
necesita. El desarrollador no se preocupa cómo funciona ya que se lo delega a Spring.

13/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

8.2. Lenguaje de Consultas JPQL


El lenguaje de consultas JPQL (Java Persistence Query Language) podría considerare como una
versión orientada a objetos del SQL. Los usuarios familiarizados con SQL deberían encontrar al JPQL fácil de
aprender y usar.
La principal diferencia es que en SQL trabaja con bases de datos relacionales y las consultas hacen
referencia a tablas y campos. En JPQL nos enfocamos en el modelo de clases y las consultas se hacen
sobre a clases y sus atributos. Nunca se hace referencia a ninguna tabla o base de datos. Luego el motor de
persistencia de JPA se encargará de traducir las consultas JPQL a SQL automáticamente para aplicarlas en
la base de datos relacional.
JPQL puede recuperar datos mediante la cláusula SELECT, puede hacer a granel actualizaciones
con cláusula UPDATE y DELETE cláusula.

8.2.1. Estructura de Consulta


Una consulta SELECT en JPQL consiste de 6 cláusulas con el siguiente formato:

SELECT ... FROM ... [WHERE ...] [GROUP BY ... [HAVING ...]] [ORDER BY ...]
Las primeras 2 cláusulas SELECT y FROM son requeridas. Las demás son opcionales.

La estructura para DELETE y UPDATE son más sencillas:

DELETE FROM ... [WHERE ...]

UPDATE ... SET ... [WHERE ...]

8.2.2. Ejemplos de consultas JPQL


Una consulta simple para obtener todos los objetos cliente sería:

SELECT c FROM Cliente c


Una consulta para obtener los objetos clientes cuyo id es mayor a 20

SELECT c FROM Cliente c WHERE c.id > 20


Una consulta para obtener un objeto clientes cuyo id es un valor a pasar como parámetro en una variable ?1 :

SELECT c FROM Cliente c WHERE c.id > ?1


Una consulta para obtener los objetos cliente de la localidad con código postal 2000:

SELECT c FROM Cliente c JOIN c.localidad l WHERE l.codPostal=’2000’


Una consulta para obtener los objetos cliente de la localidad con un código postal a ser pasador por
parámetro en ?1 y ordenado por apellido:

SELECT c FROM Cliente c JOIN c.localidad l WHERE l.codPostal = ?1 ORDER BY c.apellido


ASC
Dado que JPQL los parámetros también pueden ser objetos también podríamos obtener los objetos clientes
de una localidad específica pasando el objeto Localidad como parámetro.

SELECT c FROM Cliente c WHERE c.localidad = ?1


Una consulta para obtener los objetos cliente cuyo nombre es similar a un parámetro:

SELECT c FROM Cliente c WHERE c.name LIKE ‘%?1%’


Una consulta para obtener los objetos cliente cuyo nombre o apellido empiecen con el texto de dos
parámetros distintos respectivamente:

SELECT c FROM Cliente c WHERE c.name LIKE ‘?1%’ OR c.apellido LIKE ‘?2%’

14/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

Una consulta para obtener los objetos Localidad cuya descripción empiece con ‘a’ sin importar mayúsculas o
minúsculas y esté ordenada por código postal:

SELECT l FROM Localidad l WHERE UPPER(l.descripcion) LIKE UPPER(‘?1%’) ORDER BY


l.codPostal
Una consulta para obtener los objetos Localidad que tengan al menos 10 clientes:

SELECT l FROM Localidad l JOIN l.clientes c GROUP BY l Having Count(c) >= 10


O bien:

SELECT loc FROM Localidad loc WHERE size(loc.clientes) >= 10

8.2.3. Dao y consultas JPQL


Estas consultas las podemos usar para casos específicos del dao que no estén cubiertos por los métodos
que ofrece el JpaRepository. Por ejemplo, el código del ClienteDao se vería así:

public interface ClienteDao extends JpaRepository<Cliente, Long> {

@Query("SELECT c FROM Cliente c WHERE c.localidad = ?1")


public Collection<Cliente> buscarClientesPorLocalidad(Localidad l);

@Query("SELECT c FROM Cliente c WHERE c.name LIKE ‘%?1%’")


public Collection<Cliente> buscarClientesPorNombre(String nombre);
}

8.2.4. La cláusula FROM


La cláusula FROM define de que clases entidad se obtiene la información. JPA luego se encarga de
traducirlo a las tablas de la base de dato.
La sintaxis del FROM de JPQL es similar a SQL pero usa las clases entidad en vez de las tabals.

SELECT c FROM Cliente c


Como se ve, la consulta hace referencia a la clase Cliente y a los objetos que pueda devolver y no a la tabla
donde puedan estar los registros. Además se usa un alias o variable “c” que se puede utilizar en otras partes
de la consulta para hacer referencia a la clase Cliente.

8.2.4.1. Inner Joins


Si se quiere seleccionar información de muchas entidades hay que unir las entidades en la cláusula FROM.
La definición de la clase Cliente provee la información necesaria de sus relaciones con otras clases entidades
para hacer el join con localidad y no es necesario agregar cláusulas ON para indicar con que campos id o
claves foráneas se hace el join. En su lugar se indica el atributo por el cual existe la relación con la otra
entidad.

SELECT c FROM Cliente c a JOIN c.localidad loc WHERE loc.codPostal > 1000

SELECT DISTINCT loc FROM Localidad loc a JOIN loc.clientes c WHERE loc.codPostal LIKE
‘%0’ OR c.id > 20
Ahora teniendo en cuenta las siguientes clases:

15/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

Esta consulta obtiene los autores que han publicado libros en la editorial 'XYZ Press'

SELECT DISTINCT a FROM Autor a INNER JOIN a.libros b WHERE b.editorial.nombre =


'Pearson'
Las cláusulas INNER JOIN y JOIN son equivalentes.
Los JOINs de entidades no relacionadas no son soportados por JPA automáticamente, pero se puede usar el
WHERE para buscar la igualdad de atributos.

SELECT c FROM Cliente c, OtraClase oc WHERE c.id = oc.id

8.2.4.2. Left Outer Joins

En el ejemplo anterior se requiere las entidades satisfagan la condición del join. La segunda consulta
devuelve sólo las localidades que tengan al menos un cliente. Si hubiera una localidad con código postal 100
pero sin clientes, no sería devuelta ya que requiere que exista la relación.
Si se quisiera considerar localidades que no tengan clientes se debe usar LEFT JOIN.

SELECT DISTINCT loc FROM Localidad loc LEFT JOIN loc.clientes c WHERE loc.codPostal LIKE
‘%0’ OR c.id > 20

8.2.4.3. Condiciones adicionales para Join


Los ejemplos anteriores usan la asociación definida para hacer el join de entidades pero a veces se puede
querer que le join satisfaga condiciones adicionales. Esto también se puede hacer en JOIN o LEFT JOIN
usando ON.

SELECT c FROM Cliente c a JOIN c.localidad loc ON loc.codPostal > 1000

8.2.4.4. Joins Implícitos


Los joins implícitos se crean usando el operador “.” Para navegar las entidades:

SELECT c FROM Cliente c a WHERE c.localidad.codPostal > 1000


Como se ve, usando el operador “.” se navega a través del atributo localidad de la entidad Cliente c hasta la
Localidad. Esto crea un JOIN implícito desde el Cliente a la Localidad que luego se traduce a un JOIN en el
SQL que genera JPA.

Por ejemplo esta consulta que tiene dos join:


SELECT DISTINCT a FROM Autor a INNER JOIN a.libros b INNER JOIN b.editorial e WHERE
e.nombre = 'Pearson'
Se podría escribir de esta manera con un join implícito:
SELECT DISTINCT a FROM Autor a INNER JOIN a.libros b WHERE b.editorial.nombre =
'Pearson'

8.2.5. Proyección: La cláusula SELECT


La proyección de la consulta define qué información se obtiene de la base de datos a partir de clases
entidades con la cláusula SELECT. Esta parte es muy diferente a SQL. En SQL uno especifica un conjunto

16/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

de columnas y funciones como proyección. Uno puede hacer lo mismo en JPQL seleccionando un conjunto
de atributos de entidades, escalares o funciones como proyección.

8.2.5.1. Entidad
La forma más común de usar la proyección es por entidad, es decir que el select devuelva un objeto
completo de una clase dada por cada registro que encuentre.

SELECT c FROM Cliente c

8.2.5.2. Distinct

El operador encuentre distinct remueve duplicados de la proyección JPQL. Ejemplo:

SELECT DISTINCT loc FROM Localidad loc JOIN Cliente c WHERE c.nombre LIKE ‘a%’
Esta consulta devuelve las localidades donde hay clientes cuyo nombre empieza con la letra a. Pero en una
localidad (por ejemplo: Rosario) puede haber muchos clientes con esa característica por lo que la consulta
devolverá la localidad Rosario tantas veces como clientes hay con el nombre que empiece con la letra a. Por
eso podemos aplicar el operador DISTINCT para que elimine los duplicados que genera la consulta.

Ejemplo:

SELECT a FROM Autor a JOIN a.libros b JOIN b.editorial e WHERE e.id >1
Devolvería el mismo autor varias veces, mientras que la siguiente consulta elimina los duplicados:

SELECT DISTINCT a FROM Autor a JOIN a.libros b JOIN b.editorial e WHERE e.id >1

8.2.6. Restricción: La cláusula WHERE


Con WHERE se puede restringir los resultados de la consulta.
JPQL soporta un conjunto de operadores básicos para definir expresiones de comparación. Muchas de ellas
son idénticas a los operadores soportados por SQL y se pueden combinar con los operadores lógicos AND,
OR y NOT en expresiones más complejas.

8.2.6.1. Operadores para valores simples

SELECT a FROM Autor a WHERE

• a.id = 10
• a.id <> 10
• a.id > 10
• a.id => 10
• a.id < 10
• a.id <= 10
• a.id BETWEEN 5 and 10
• a.nombre LIKE ‘%ua%’
• a.nombre NOT LIKE ‘%ua%’
• a.nombre LIKE ‘_ua_’
• a.nombre IS NULL
• a.nombre IS NOT NULL
• In: a.nombre IN ('Martin', 'Kent')

17/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

En LIKE el caracter % representa cualquier secuencia de caracteres. Este ejemplo restringe que el
resultado de la consulta a los autores cuyo nombre contiene el String “ua” como Juan, Juanjo, Juan Martin,
Luana, etc. También se puede usar “_” para representar solo un caracter. Por ejemplo ‘_ua_’ solo devolvería
“Juan”. También se puede negar con el operador NOT para excluir los clientes con ese tipo de nombre.

8.2.6.2. Operadores para colecciones


Estos operadores se utilizan sobre atributos o valores que son de tipo colección.

SELECT loc FROM Localidad loc WHERE loc.clientes IS EMPTY


Restinge a localidades que no tengan clientes.

SELECT loc FROM Localidad loc WHERE loc.clientes IS NOT EMPTY


Restinge a localidades que tengan clientes.

SELECT loc FROM Localidad loc WHERE size(loc.clientes) > 2

SELECT a FROM Autor a WHERE size(a.libros) > 2


Restringe los resultados a localidades que tengan más de 2 clientes.

SELECT loc FROM Localidad loc WHERE ?1 MEMBER OF loc.clientes


Restringe los resultados a las localidades que tengan al objeto cliente pasado en la variable “?1”
entre sus de su clientes.
Se pueden usar uno o más operadores para restringir el resultado de la consulta.
La siguiente consulta devuelve las localidades cuyo código postal empiece con “2”, la descripción no sea null
y tenga al menos 5 clientes:

SELECT loc FROM Localidad loc WHERE loc.codPostal like ‘2%’ and loc.descripcion IS NOT
NULL and size(loc.clientes) >= 5

8.2.7. Funciones
Las funciones son una característica ponderosa de JPQL y premiten hacer operaciones básicas en las
cláusulas WHERE y SELECT. Se pueden usar las siguientes funciones:

• upper(String s): transforma un String a mayúsculas.


• lower(String s): transforma un String a minúsculas.
• current_date(): devuelve la fecha actual de la base de datos.
• current_time(): devuelve la hora actual de la base de datos.
• current_timestamp(): devuelve la fecha y hora actual de la base de datos.
• substring(String s, int offset, int length): devuelve una parte de un String s.
• trim(String s): remueve los espacios en blanco en el comienzo y final de un String s.
• length(String s): retorna el largo de un String s.
• locate(String search, String s, int offset): retorna la posición de un String search dentro un String s. La
búsqueda comienza en la posición offset.
• abs(Numeric n): retrona el valor absolute para un número dado.
• sqrt(Numeric n): retorna la raiz cuadrada de un número dado.
• mod(Numeric dividend, Numeric divisor): retorna el resto de una división.
• treat(x as Type): Hace un downcasts x al tipo de dato Type. En caso de polimorfismo.
• size(c): devuelve el tamaño de una colección c.
• index(orderdCollection): retorna la ubicación de un valor dentro de una colección ordenada.
• Concat(String s1, String s2): Concatena dos o mas string. Ejemplo: SELECT a FROM Autor a
WHERE CONCAT(a.nombre, a.apellido) LIKE '%Martin%'

18/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

8.2.8. Agrupamiento: La cláusula GROUP BY y HAVING


Cuando se usan funciones de agregación como count() en el select, es necesario hacer referencia a
todos los atributos que no son parte de la función en la cláusula GROUP BY. Suelen ser muy útiles para
hacer sub-consultas.
La siguiente consulta muestra cómo usar la función count() para mostrar cuantas veces aparece el mismo
apellido en instancias de Autor.

SELECT a.apellido, COUNT(a) FROM Autor a GROUP BY a.apellido


La cláusula HAVING es similar al WHERE y permite definir restricciones adicionales a la consulta. La
principal diferencia es que las restricciones de HAVING se aplican solo al grupo y no a la fila.

La siguiente consulta obtiene todos los apellidos que empiezan con ‘B’ y cuenta cuantas instancias
hay de cada una:

SELECT a.apellido, COUNT(a) AS cnt FROM Autor a GROUP BY a.apellido HAVING a.apellido
LIKE 'B%'
La siguiente consulta obtiene todos las biografías que contienen la palabra ‘Martin’ y cuenta cuantas
instancias hay de cada una:

SELECT a.bio, COUNT(a) AS cnt FROM Autor a GROUP BY a.bio HAVING a.bio LIKE '%Martin%'
La siguiente consulta devuelve las editoriales que tienen 2 o mas autores:

SELECT DISTINCT e FROM Editorial e JOIN e.libros b JOIN b.autores a GROUP BY e HAVING
count(a) >= 2
La siguiente consulta devuelve las editoriales que tienen publicados 2 o más libros:

SELECT e FROM Editorial e JOIN e.libros b GROUP BY e HAVING count(b) >= 3


La siguiente consulta devuelve los autores que tienen publicados 2 o más libros y tienen la palabra “Martin”
en su biografía:

SELECT a FROM Autor a JOIN a.libros b GROUP BY a HAVING a.bio LIKE '%Martin%' AND
count(b) >= 2 ORDER BY a.nombre
La siguiente consulta devuelve los autores que han publicado libros para dos o más editoriales distintas:

SELECT a FROM Autor a JOIN a.libros b JOIN b.editorial e GROUP BY a HAVING


COUNT(DISTINCT e) >=2

8.2.9. Ordenamiento: La cláusula ORDER BY


Uno puede definir el orden en que la base de datos retorne los resultados de la consulta con la
cláusula ORDER BY. Su definición y uso es similar a SQL. Se pueden usar uno o muchos atributos al usar
ORDER BY y también especificar si el orden de cada atributo es ascendente con ASC o descendente con
DESC.

SELECT c FROM Cliente c WEHERE c.id BETWEEN 50 AND 100 ORDER BY c.apellido ASC, c.nombre
DESC

SELECT a FROM Autor a ORDER BY a.nombre, a.apellido

8.2.10. Sub-consultas
Una sub-consulta es una consulta embebida dentro de otra consulta. Es una característica poderosa
utilizada en SQL. JPQL soporta las sub-consultas sólo dentro de la cláusula WHERE y no el SELECT o
FROM.

19/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

Las sub-consultas pueden devolver uno o muchos registros y pueden usar alias definidos en la
consulta contenedora.
La siguiente sub-consulta devuelve la cantidad de libros que ha escrito cada autor a. La consulta principal
devuelve los objetos autor que han escrito uno o más libros.

SELECT a FROM Autor a WHERE (SELECT count(b) FROM Libro b WHERE a MEMBER OF b.autores)>1

8.2.11. Polimorfismo
Cuando se utiliza una estrategia de herencia que soporta consulta polimórficas, una consulta
devuelve todas las instancias de una determinada clase y sus subclases. En el diagrama de clases un Autor
escribe publicaciones que pueden ser libros o artículos web. La clase publicación es abstracta por lo que no
habrá instancias reales de esta clase pero si de Libro y Articulo.

La siguiente consulta devuelve una colección con todos los objetos Articulo y objetos Libro que
existen:

SELECT p FROM Publication p


Esta consulta devuelve los libros y artículos que tengan 2 o más autores:

SELECT p FROM Publication p WHERE size(p.autores) >= 2

Si en un futuro se agregan nuevas subclases de Publicacion (por ejemplo ObraTeatro y GuionCine),


las consultas de arriba también devolverían instancias de esas subclases.

La siguiente consulta devuelve una colección sólo con todos los objetos Articulo que existen pero no
los objetos de tipo Libro:

SELECT ar FROM Articulo ar


La consulta anterior sigue siendo válida en este diagrama de clases.

SELECT DISTINCT a FROM Autor a INNER JOIN a.libros b WHERE b.editorial.nombre =


'Pearson'

20/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

8.2.12. Ejercicios de consultas JPQL

8.2.12.1. Verificar consultas del apunte


Ingrese a https://jpql-console.herokuapp.com/jpql/console y verifique las consultas jpql de este
apunte.
Adapte las consultas del modelo de clases de cliente para que funcionen con el modelo de clases
provisto en el sitio.

9. Apéndice
9.1. Principios SOLID
En ingeniería de software, SOLID (Single responsibility, Open-closed, Liskov substitution, Interface
segregation and Dependency inversion) es un acrónimo mnemónico introducido por Robert C. Martin a
comienzos de la década del 2000 que representa cinco principios básicos de la programación orientada a
objetos y el diseño. Cuando estos principios se aplican en conjunto es más probable que un desarrollador
cree un sistema con alta cohesión y bajo acoplamiento que sea fácil de mantener y ampliar con el tiempo.

9.1.1. Single responsibility principle


Principio de responsabilidad. La noción de que un objeto solo debería tener una única
responsabilidad.
Este principio trata de destinar cada clase a una finalidad sencilla y concreta. En muchas ocasiones
estamos tentados a poner un método reutilizable que no tienen nada que ver con la clase simplemente
porque lo utiliza. En ese momento pensamos "Ya que estamos aquí, para que voy a crear una clase para
realizar esto. Directamente lo pongo aquí".
El problema surge cuando tenemos la necesidad de utilizar ese mismo método desde otra clase. Si
no se refactoriza en ese momento y se crea una clase destinada para la finalidad del método, nos toparemos
a largo plazo con que las clases realizan tareas que no deberían ser de su responsabilidad.
Con la anterior mentalidad nos encontraremos, por ejemplo, con un algoritmo de formateo de
números en una clase destinada a leer de la base de datos porque fue el primer sitio donde se empezó a
utilizar. Esto conlleva a tener métodos difíciles de detectar y encontrar de manera que el código hay que
tenerlo memorizado en la cabeza.

9.1.2. Open/closed
Principio de abierto/cerrado. La noción de que las “entidades de software deben estar abiertas para
su extensión, pero cerradas para su modificación”.
Principio atribuido a Bertrand Meyer que habla de crear clases extensibles sin necesidad de entrar al
código fuente a modificarlo. Es decir, el diseño debe ser abierto para poderse extender pero cerrado para
poderse modificar. Aunque dicho parece fácil, lo complicado es predecir por donde se debe extender y que
no tengamos que modificarlo. Para conseguir este principio hay que tener muy claro como va a funcionar la
aplicación, por donde se puede extender y como van a interactuar las clases.

El uso más común de extensión es mediante la herencia y la reimplementación de métodos. Existe


otra alternativa que consiste en utilizar métodos que acepten una interface de manera que podemos ejecutar
cualquier clase que implemente ese interface. En todos los casos, el comportamiento de la clase cambia sin
que hayamos tenido que tocar código interno.

Llega un momento en que las necesidades pueden llegar a ser tan imprevisibles que nos topemos
que con los métodos definidos en el interface o en los métodos extensibles, no sean suficientes para cubrir
las necesidades. En este caso no habrá más remedio que romper este principio y refactorizar.

9.1.3. Liskov substitution principle


Principio de sustitución de Liskov. La noción de que los “objetos de un programa deberían ser
reemplazables por instancias de sus subtipos sin alterar el correcto funcionamiento del programa”. Ver
también diseño por contrato.

21/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

Este principio fue creado por Barbara Liskov y habla de la importancia de crear todas las clases
derivadas para que también puedan ser tratadas como la propia clase base. Cuando creamos clases
derivadas debemos asegurarnos de no reimplementar métodos que hagan que los métodos de la clase base
no funcionases si se tratasen como un objeto de esa clase base.

9.1.4. Interface segregation principle


Principio de segregación de la interfaz. La noción de que “muchas interfaces cliente específicas son
mejores que una interfaz de propósito general”.
Este principio fue formulado por Robert C. Martin y trata de algo parecido al primer principio. Cuando
se definen interfaces estos deben ser específicos a una finalidad concreta. Por ello, si tenemos que definir
una serie de métodos abstractos que debe utilizar una clase a través de interfaces, es preferible tener
muchos interfaces que definan pocos métodos que tener un interface con muchos métodos.
El objetivo de este principio es principalmente poder reaprovechar los interfaces en otras clases. Si
tenemos un interface que compara y clona en el mismo interface, de manera más complicada se podrá
utilizar en una clase que solo debe comparar o en otra que solo debe clonar.

9.1.5. Dependency inversion principle


Principio de inversión de la dependencia. La noción de que se debe “depender de abstracciones, no
depender de implementaciones”.
También fue definido por Robert C. Martin. El objetivo de este principio conseguir desacoplar las
clases. En todo diseño siempre debe existir un acoplamiento pero hay que evitarlo en la medida de lo posible.
Un sistema no acoplado no hace nada pero un sistema altamente acoplado es muy difícil de mantener.
El objetivo de este principio es el uso de abstracciones para conseguir que una clase interactúe con
otras clases sin que las conozca directamente. Es decir, las clases de nivel superior no deben conocer las
clases de nivel inferior. Dicho de otro modo, no debe conocer los detalles. Existen diferentes patrones como
la inyección de dependencias o service locator que nos permiten invertir el control.

9.2. Ejemplo de uso de interfaces, implementaciones y principios


SOLID
En el siguiente ejemplo se ve el uso de interfaces cuyo diseño cumple con los principios de diseño
SOLID:

22/23 27/02/2018 20:54:00


Framework Spring, MVC y DAO - Diseño de Sistemas
Autor: Ignacio Paz Versión : 1.01 [27/02/18]
Cátedra Diseño de Sistemas UTN – F.R.Ro.

La Fabrica necesita hacer trabajar a cualquier objeto que responda al método trabajar() mientras que el
Resturant le va a servir comida a cualquier objeto que responda al método comer().
Entonces se pueden definir dos interfaces Trabajador y Comensal (sin implementación) bien específicas
siguiendo el principio de única responsabilidad. De esta forma fabrica y el restaurant no se preocupan de
que clase es la instancia realmente mientras que implementen la interfaz Trabajador o Comensal
respectivamente. Ahí se produce el principio de inversión de dependencia ya que el la frabrica y el
restaurant tienen dependendencias sobre las interfaces y no sobre las clases que las implementen.
La colección trabajadores tendrá una mezcla de instancias de Robot, Operador y SuperTrabajador pero la
Fabrica los ve como Trabajador, ya que es lo único que conoce. De esa forma se cumple con el principio de
subsitución de Liskov ya cualquiera de esas tres instancias son substituibles a los ojos de la Fabrica y
responden a lo que define la interfaz Trabajador. En el caso que no existiera la interfaz Comensal y el método
comer() estuviera en la interfaz Trabajador, el Cliente se vería obligadoa implementar esa interfaz y el
método trabajar() de forma que no haga nada o tire un error. Ahí se produciría una falta a ese principio ya
que el cliente no es sustuible como trabajador ya que realmente no puede trabajar.
Por eso, dado hay 4 clases que responden a los mismos métodos en algunos casos y en otros no, se aplica
el principio de segregacion de interfaz, creando dos interfaces específicas y que cada clase implemente
las interfaces a las que realemente puede dar comportamiento.
Por último, el uso de interfaces permite el principio abierto-cerrado, ya que si quisieramos agregar una
máquina que solo trabaja, no necesitamos cambiar nada de lo que existe (cerrado para modificación) sino
que solo tenemos que crear una clase Maquina con el método trabajar() que implemente la interfaz
Trabajador (abierto para extensión).

9.3. Ejercicio
Siguiendo los principios SOLID, modifique el diseño anterior para agregar:
• Una Maquina que puede trabajar y se le debe cargar combustible.
• Un vehículo que no trabaja pero se le debe cargar combustible.
• Una estación de servicio que carga combustible.

10. Bibliografía
• https://projects.spring.io/spring-framework/#quick-start
• https://martinfowler.com/eaaCatalog/frontController.html
• https://martinfowler.com/eaaCatalog/repository.html
• http://www.jtech.ua.es/j2ee/publico/spring-2012-13/sesion03-apuntes.html
• https://www.martinfowler.com/bliki/AnemicDomainModel.html
• https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html
• https://spring.io/guides/gs/accessing-data-jpa/
• https://docs.spring.io/spring-
data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html
• https://docs.oracle.com/html/E13946_01/ejb3_langref.html
• http://www.oodesign.com/design-principles.html
• https://es.wikipedia.org/wiki/SOLID
• https://www.genbetadev.com/paradigmas-de-programacion/solid-cinco-principios-basicos-de-diseno-
de-clases
• http://www.objectdb.com/java/jpa/query
• https://es.wikipedia.org/wiki/Java_Persistence_Query_Language
• https://www.tutorialspoint.com/es/jpa/jpa_jpql.htm
• https://docs.oracle.com/html/E13946_01/ejb3_langref.html
• https://www.thoughts-on-java.org/jpql/
• https://www.thoughts-on-java.org/complete-guide-inheritance-strategies-jpa-hibernate/

11. Historia de Versiones del documento


Versión Fecha Autor Descripción
1.01 27/02/2018 Versión inicial

23/23 27/02/2018 20:54:00

S-ar putea să vă placă și