Nos vamos a encontrar muchas veces, casos en donde el responder con un JSON conteniendo todos los campos de una tabla en todos sus registros, es inviable, o, por lo menos, muy caro en comunicaciones. Imaginaros un registro de Clientes, o de Productos que pese 2 Megas, y que os piden los Clientes, para hacer una lista de nombres…. bien, una de las soluciones, la que hoy vemos, es utilizar JPA Projection
La idea
Mas o menos, ya he presentado el problema, la idea es enviar la informacion necesaria, y no montañas de informacion que a veces, puede ser hasta delicada…
Nosotros vamos a realizar el ejercicio con un registro que no tiene ese problema, y es el registro de Cine. Pensad que en un caso real, puede que este fichero tuviera muchos mas campos, pero para ver como funciona, nos bastara. Este caso esta basado en el proyecto «Los Cines» descritos a partir de Visión de conjunto con Spring
Todo lo que haremos es trabajar con el JPA, pero por si acaso, os recuerdo que en el pom.xml deberá estar
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
El objeto DTO
Empezamos creando un objeto DTO con la informacion que queremos enviar; en este caso, se me ha ocurrido esta
package com.recursosformacion.lcs.model_dto;
public class CineProjectionNombre {
private Long id_cine;
private String ci_nombre;
private String ci_barrio;
public CineProjectionNombre(Long id_cine, String ci_nombre, String ci_barrio) {
super();
this.id_cine = id_cine;
this.ci_nombre = ci_nombre;
this.ci_barrio = ci_barrio;
}
public Long getId_cine() {
return id_cine;
}
public String getCi_nombre() {
return ci_nombre;
}
public String getCi_barrio() {
return ci_barrio;
}
}
Repositorio
Para conseguir la funcionalidad deseada, le tendremos que añadir al repositorio de Cine la query que vamos a utilizar, y el objeto a construir. No deberá quedar asi
package com.recursosformacion.lcs.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.recursosformacion.lcs.model.Cine;
import com.recursosformacion.lcs.model_dto.CineProjectionNombre;
public interface ICine extends JpaRepository<Cine, Long>{
@Query("SELECT new com.recursosformacion.lcs.model_dto.CineProjectionNombre(c.id_cine, c.ci_nombre, c.ci_barrio) FROM Cine c")
List<CineProjectionNombre> findAllCineProjectionNombre();
}
Hemos utilizado @Query para definir el objeto a construir, y el metodo que utilizaremos, y que debe coincidir con «findAll» y el objeto creado
El servicio
En el servicio, deberemos añadir el método que tenemos que utilizar, explicando el que definimos en la interface, y que puede ser
public List<CineProjectionNombre> getAllCineProjectionNombre(){
return cineRepository.findAllCineProjectionNombre();
}
Ahora, solo nos queda hacer que el controlador sepa llamarlo
El controlador
Necesitamos un comando mas, y hacer que el controlador sea sensible a la nueva orde. La orden que he creado, siguiendo la estructura habitual será
Método | URL | Acción |
GET | /api/cine/direccion | Devuelve todos los cines, pero solo facilita id, nombre y barrio |
y el método que tengo que añadir al controlar escrito aqui, será:
public List<CineProjectionNombre> getAllCineProjectionNombre(){
return cineRepository.findAllCineProjectionNombre();
}
Como veis, solo tengo que invocar el servicio
Las pruebas
Podemos probar el nuevo comando
y vemos como en data, solo nos aparece la información prevista
Conclusión
Todo este desarrollo lo teneis explicado con mas detalle en youTube (a partir de 1/02/24) , y, aunque es conveniente que intentéis escribirlo TODO vosotros, si queréis renunciar a ello, lo teneis tambien en GitHub
Este desarrollo esta basado en un fuente creado para explicar distintos temas de SpringBoot, tal y como se indica en Visión de conjunto con Spring
Relacionado
Descubre más desde Recursos para formacion
Suscríbete y recibe las últimas entradas en tu correo electrónico.