Spring Boot 3 - Desarrollo API Rest: Aula 4
This commit is contained in:
parent
fb7ea652e4
commit
c391edc321
@ -1,18 +1,24 @@
|
||||
package med.voll.api.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import med.voll.api.medico.DatosListadoMedicos;
|
||||
import med.voll.api.medico.DatosRegistroMedico;
|
||||
import med.voll.api.medico.Medico;
|
||||
import med.voll.api.medico.MedicoRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/medicos")
|
||||
public class MedicoController {
|
||||
|
||||
// No es recomendable usar @Autowired a nivel de declaración pues genera
|
||||
// problemas al realizar pruebas unitarias
|
||||
/* No es recomendable usar @Autowired a nivel de declaración pues genera
|
||||
problemas al realizar pruebas unitarias */
|
||||
@Autowired
|
||||
private MedicoRepository medicoRepository;
|
||||
@PostMapping
|
||||
@ -20,4 +26,8 @@ public class MedicoController {
|
||||
medicoRepository.save(new Medico(datosRegistroMedico));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Page<DatosListadoMedicos> listadoMedicos(@PageableDefault(size = 5) Pageable paginacion) {
|
||||
return medicoRepository.findAll(paginacion).map(DatosListadoMedicos::new);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package med.voll.api.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import med.voll.api.paciente.DatosListadoPacientes;
|
||||
import med.voll.api.paciente.DatosRegistroPaciente;
|
||||
import med.voll.api.paciente.Paciente;
|
||||
import med.voll.api.paciente.PacienteRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/pacientes")
|
||||
public class PacienteController {
|
||||
|
||||
/* No es recomendable usar @Autowired a nivel de declaración pues genera
|
||||
problemas al realizar pruebas unitarias */
|
||||
@Autowired
|
||||
private PacienteRepository pacienteRepository;
|
||||
@PostMapping
|
||||
public void registrarPaciente(@RequestBody @Valid DatosRegistroPaciente datosRegistroPaciente) {
|
||||
pacienteRepository.save(new Paciente(datosRegistroPaciente));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Page<DatosListadoPacientes> listadoPacientes(@PageableDefault(size = 5) Pageable paginacion) {
|
||||
return pacienteRepository.findAll(paginacion).map(DatosListadoPacientes::new);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package med.voll.api.medico;
|
||||
|
||||
public record DatosListadoMedicos(String nombre, String especialidad, String documento, String email) {
|
||||
|
||||
public DatosListadoMedicos (Medico medico) {
|
||||
this(medico.getNombre(),
|
||||
medico.getEspecialidad().toString(),
|
||||
medico.getDocumento(),
|
||||
medico.getEmail());
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,7 @@ public class Medico {
|
||||
private String email;
|
||||
private String telefono;
|
||||
private String documento;
|
||||
@Enumerated
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Especialidad especialidad;
|
||||
@Embedded
|
||||
private Direccion direccion;
|
||||
@ -30,8 +30,8 @@ public class Medico {
|
||||
public Medico(DatosRegistroMedico datosRegistroMedico) {
|
||||
this.nombre = datosRegistroMedico.nombre();
|
||||
this.email = datosRegistroMedico.email();
|
||||
this.telefono = datosRegistroMedico.telefono();
|
||||
this.documento = datosRegistroMedico.documento();
|
||||
this.telefono = datosRegistroMedico.telefono();
|
||||
this.especialidad = datosRegistroMedico.especialidad();
|
||||
this.direccion = new Direccion(datosRegistroMedico.direccion());
|
||||
}
|
||||
|
@ -2,4 +2,5 @@ package med.voll.api.medico;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface MedicoRepository extends JpaRepository<Medico, Long> {}
|
||||
public interface MedicoRepository extends JpaRepository<Medico, Long> {
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package med.voll.api.paciente;
|
||||
|
||||
public record DatosListadoPacientes(String nombre, String documento, String email) {
|
||||
|
||||
public DatosListadoPacientes(Paciente medico) {
|
||||
this(medico.getNombre(),
|
||||
medico.getDocumento(),
|
||||
medico.getEmail());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package med.voll.api.paciente;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import med.voll.api.direccion.DatosDireccion;
|
||||
|
||||
public record DatosRegistroPaciente(
|
||||
@NotBlank String nombre,
|
||||
@NotBlank @Email String email,
|
||||
@NotBlank String telefono,
|
||||
@NotBlank @Pattern(regexp = "\\d{4,6}") String documento,
|
||||
@NotNull @Valid DatosDireccion direccion
|
||||
) {}
|
@ -0,0 +1,35 @@
|
||||
package med.voll.api.paciente;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import med.voll.api.direccion.Direccion;
|
||||
|
||||
@Table(name="pacientes")
|
||||
@Entity(name="Paciente")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
public class Paciente {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String nombre;
|
||||
private String email;
|
||||
private String telefono;
|
||||
private String documento;
|
||||
@Embedded
|
||||
private Direccion direccion;
|
||||
|
||||
public Paciente(DatosRegistroPaciente datosRegistroPaciente) {
|
||||
this.nombre = datosRegistroPaciente.nombre();
|
||||
this.email = datosRegistroPaciente.email();
|
||||
this.documento = datosRegistroPaciente.documento();
|
||||
this.telefono = datosRegistroPaciente.telefono();
|
||||
this.direccion = new Direccion(datosRegistroPaciente.direccion());
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package med.voll.api.paciente;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface PacienteRepository extends JpaRepository<Paciente, Long> {
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
spring.datasource.url=jdbc:mysql://192.168.0.8/vollmed_api
|
||||
spring.datasource.username=alura
|
||||
spring.datasource.password=alura
|
||||
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
@ -0,0 +1,16 @@
|
||||
create table pacientes(
|
||||
|
||||
id bigint not null auto_increment,
|
||||
nombre varchar(100) not null,
|
||||
email varchar(100) not null unique,
|
||||
documento varchar(6) not null unique,
|
||||
telefono varchar(20) not null,
|
||||
calle varchar(100) not null,
|
||||
distrito varchar(100) not null,
|
||||
complemento varchar(100),
|
||||
numero varchar(20),
|
||||
ciudad varchar(100) not null,
|
||||
|
||||
primary key(id)
|
||||
|
||||
);
|
20
010_spring_boot/populate_vollmed_db/populate_medicos.sql
Normal file
20
010_spring_boot/populate_vollmed_db/populate_medicos.sql
Normal file
@ -0,0 +1,20 @@
|
||||
USE vollmed_api;
|
||||
INSERT INTO vollmed_api.medicos(nombre, email, telefono, documento, especialidad, calle, distrito, complemento, ciudad, numero)
|
||||
VALUES
|
||||
('Cuarto Medico', 'dr_4@voll.med', '44444', '444444', 'CARDIOLOGIA', 'calle 4', 'distrito 4', 'prueba', 'Santiago', '4'),
|
||||
('Quinto Medico', 'dr_5@voll.med', '55555', '555555', 'PEDIATRIA', 'calle 5', 'distrito 5', 'prueba', 'Santiago', '5'),
|
||||
('Sexto Medico', 'dr_6@voll.med', '66666', '666666', 'ORTOPEDIA', 'calle 6', 'distrito 6', 'prueba', 'Santiago', '6'),
|
||||
('Septimo Medico', 'dr_7@voll.med', '77777', '777777', 'GINECOLOGIA', 'calle 7', 'distrito 7', 'prueba', 'Santiago', '7'),
|
||||
('Octavo Medico', 'dr_8@voll.med', '88888', '888888', 'CARDIOLOGIA', 'calle 8', 'distrito 8', 'prueba', 'Santiago', '8'),
|
||||
('Noveno Medico', 'dr_9@voll.med', '99999', '999999', 'PEDIATRIA', 'calle 9', 'distrito 9', 'prueba', 'Santiago', '9'),
|
||||
('Decimo Medico', 'dr_10@voll.med', '10101', '101010', 'ORTOPEDIA', 'calle 10', 'distrito 10', 'prueba', 'Santiago', '10'),
|
||||
('Onceavo Medico', 'dr_11@voll.med', '11011', '110111', 'CARDIOLOGIA', 'calle 11', 'distrito 11', 'prueba', 'Santiago', '11'),
|
||||
('Doceavo Medico', 'dr_12@voll.med', '12121', '121212', 'PEDIATRIA', 'calle 12', 'distrito 12', 'prueba', 'Santiago', '12'),
|
||||
('Treceavo Medico', 'dr_13@voll.med', '13131', '131313', 'ORTOPEDIA', 'calle 13', 'distrito 13', 'prueba', 'Santiago', '13'),
|
||||
('Catorceavo Medico', 'dr_14@voll.med', '14141', '141414', 'GINECOLOGIA', 'calle 14', 'distrito 14', 'prueba', 'Santiago', '14'),
|
||||
('Quinceavo Medico', 'dr_15@voll.med', '15151', '151515', 'CARDIOLOGIA', 'calle 15', 'distrito 15', 'prueba', 'Santiago', '15'),
|
||||
('Diesiceisavo Medico', 'dr_16@voll.med', '16161', '161616', 'PEDIATRIA', 'calle 16', 'distrito 16', 'prueba', 'Santiago', '16'),
|
||||
('Diesicieteavo Medico', 'dr_17@voll.med', '17171', '171717', 'ORTOPEDIA', 'calle 17', 'distrito 17', 'prueba', 'Santiago', '17'),
|
||||
('Diesiochoavo Medico', 'dr_18@voll.med', '18181', '181818', 'GINECOLOGIA', 'calle 18', 'distrito 18', 'prueba', 'Santiago', '18'),
|
||||
('Diecinueveavo Medico', 'dr_19@voll.med', '19191', '191919', 'CARDIOLOGIA', 'calle 19', 'distrito 19', 'prueba', 'Santiago', '19'),
|
||||
('Veinteavo Medico', 'dr_20@voll.med', '20202', '202020', 'PEDIATRIA', 'calle 20', 'distrito 20', 'prueba', 'Santiago', '20');
|
20
010_spring_boot/populate_vollmed_db/populate_pacientes.sql
Normal file
20
010_spring_boot/populate_vollmed_db/populate_pacientes.sql
Normal file
@ -0,0 +1,20 @@
|
||||
USE vollmed_api;
|
||||
INSERT INTO vollmed_api.pacientes(nombre, email, telefono, documento, calle, distrito, complemento, ciudad, numero)
|
||||
VALUES
|
||||
('Cuarto Paciente', 'paciente_4@private.cl', '44444', '444444', 'calle 4', 'distrito 4', 'prueba', 'Santiago', '4'),
|
||||
('Quinto Paciente', 'paciente_5@private.cl', '55555', '555555', 'calle 5', 'distrito 5', 'prueba', 'Santiago', '5'),
|
||||
('Sexto Paciente', 'paciente_6@private.cl', '66666', '666666', 'calle 6', 'distrito 6', 'prueba', 'Santiago', '6'),
|
||||
('Septimo Paciente', 'paciente_7@private.cl', '77777', '777777', 'calle 7', 'distrito 7', 'prueba', 'Santiago', '7'),
|
||||
('Octavo Paciente', 'paciente_8@private.cl', '88888', '888888', 'calle 8', 'distrito 8', 'prueba', 'Santiago', '8'),
|
||||
('Noveno Paciente', 'paciente_9@private.cl', '99999', '999999', 'calle 9', 'distrito 9', 'prueba', 'Santiago', '9'),
|
||||
('Decimo Paciente', 'paciente_10@private.cl', '10101', '101010', 'calle 10', 'distrito 10', 'prueba', 'Santiago', '10'),
|
||||
('Onceavo Paciente', 'paciente_11@private.cl', '11011', '110111', 'calle 11', 'distrito 11', 'prueba', 'Santiago', '11'),
|
||||
('Doceavo Paciente', 'paciente_12@private.cl', '12121', '121212', 'calle 12', 'distrito 12', 'prueba', 'Santiago', '12'),
|
||||
('Treceavo Paciente', 'paciente_13@private.cl', '13131', '131313', 'calle 13', 'distrito 13', 'prueba', 'Santiago', '13'),
|
||||
('Catorceavo Paciente', 'paciente_14@private.cl', '14141', '141414', 'calle 14', 'distrito 14', 'prueba', 'Santiago', '14'),
|
||||
('Quinceavo Paciente', 'paciente_15@private.cl', '15151', '151515', 'calle 15', 'distrito 15', 'prueba', 'Santiago', '15'),
|
||||
('Diesiceisavo Paciente', 'paciente_16@private.cl', '16161', '161616', 'calle 16', 'distrito 16', 'prueba', 'Santiago', '16'),
|
||||
('Diesicieteavo Paciente', 'paciente_17@private.cl', '17171', '171717', 'calle 17', 'distrito 17', 'prueba', 'Santiago', '17'),
|
||||
('Diesiochoavo Paciente', 'paciente_18@private.cl', '18181', '181818', 'calle 18', 'distrito 18', 'prueba', 'Santiago', '18'),
|
||||
('Diecinueveavo Paciente', 'paciente_19@private.cl', '19191', '191919', 'calle 19', 'distrito 19', 'prueba', 'Santiago', '19'),
|
||||
('Veinteavo Paciente', 'paciente_20@private.cl', '20202', '202020', 'calle 20', 'distrito 20', 'prueba', 'Santiago', '20');
|
@ -330,7 +330,8 @@ Documentación Java
|
||||
|
||||
## Agregando dependencias
|
||||
|
||||
Copiar `xml` de Spring [initializr](https://start.spring.io/), y pegar en `pom.xml`
|
||||
Copiar sección del `xml` de Spring [initializr](https://start.spring.io/), y
|
||||
pegar en `pom.xml`
|
||||
|
||||
Modificar `resources/application.properties`
|
||||
|
||||
@ -413,10 +414,11 @@ public class ProductoDao {
|
||||
En el ejemplo anterior, se utilizó JPA como tecnología de persistencia de datos
|
||||
de la aplicación.
|
||||
|
||||
**Patrón Repository**. Según el famoso libro Domain-Driven Design de Eric Evans:
|
||||
**Patrón Repository** según el famoso libro *Domain-Driven Design* de *Eric
|
||||
Evans*:
|
||||
|
||||
El repositorio es un mecanismo para encapsular el almacenamiento, recuperación y
|
||||
comportamiento de búsqueda, que emula una colección de objetos.
|
||||
> *El repositorio es un mecanismo para encapsular el almacenamiento, recuperación y
|
||||
comportamiento de búsqueda, que emula una colección de objetos.*
|
||||
|
||||
En pocas palabras, un repositorio también maneja datos y oculta consultas
|
||||
similares a DAO. Sin embargo, se encuentra en un nivel más alto, más cerca de
|
||||
@ -516,3 +518,206 @@ estableciendo una colaboración entre componentes.
|
||||
Para más información sobre la anotación, ver la
|
||||
[documentación oficial](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html)
|
||||
|
||||
## Get
|
||||
|
||||
### Consideraciones
|
||||
|
||||
Información requerida del médico
|
||||
|
||||
- Nombre
|
||||
- Especialidad
|
||||
- Documento
|
||||
- Email
|
||||
|
||||
Reglas del negocio
|
||||
|
||||
- Orden ascendente
|
||||
- Paginado, máximo 10 registros por página
|
||||
|
||||
<br>
|
||||
|
||||
En
|
||||
[MedicoController](./api_rest/api/src/main/java/med/voll/api/controller/MedicoController.java)
|
||||
se utilizo DTO para representar los datos recibi4os y devueltos a través de la
|
||||
API, *¿Por qué, en lugar de crear un DTO, no devolvemos directamente la entidad
|
||||
JPA en el Controller?*. Para esto, basta con cambiar método `listadoMedicos()`
|
||||
en el Controller a:
|
||||
|
||||
```java
|
||||
@GetMapping
|
||||
public List<Medico> listarMedicos() {
|
||||
return repository.findAll();
|
||||
}
|
||||
```
|
||||
|
||||
De esa forma, el código sería más ligero y no necesitaríamos crear el DTO
|
||||
en el proyecto. Pero, **¿es esto realmente una buena idea?**
|
||||
|
||||
#### Problemas de recepción/devolución de la entidad JPA
|
||||
|
||||
De hecho, es mucho más simple y cómodo no usar DTO, sino tratar directamente
|
||||
con entidades JPA en los Controllers. Sin embargo, este enfoque tiene algunas
|
||||
desventajas, incluida la vulnerabilidad de la aplicación a los ataques de
|
||||
*Mass Assignment*.
|
||||
|
||||
Uno de los problemas, es que al devolver una entidad JPA en un método del
|
||||
Controller, Spring generará el JSON que contiene todos sus atributos, y este no
|
||||
siempre es el comportamiento deseado.
|
||||
|
||||
Eventualmente pueden tener atributos que no se requiere que sean devueltos en el
|
||||
JSON, ya sea por razones de seguridad, en el caso de datos sensibles, o incluso
|
||||
porque no son utilizados por clientes API.
|
||||
|
||||
#### Uso de la anotación `@JsonIgnore`
|
||||
|
||||
En esta situación, se puede usar la anotación `@JsonIgnore`, que nos ayuda a
|
||||
ignorar ciertas propiedades de una clase Java cuando se serializa en un objeto
|
||||
JSON.
|
||||
|
||||
Su uso consiste en agregar la anotación a los atributos que se quieren ignorar
|
||||
cuando se genera el JSON. Por ejemplo, supongamos que tenemos una entidad JPA
|
||||
`Empleado`, en la que se quiere ignorar el atributo `salario`:
|
||||
|
||||
```java
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
@Entity(name = "Empleado")
|
||||
@Table(name = "empleados")
|
||||
public class Empleado {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String nombre;
|
||||
private String email;
|
||||
|
||||
@JsonIgnore
|
||||
private BigDecimal salario;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
En el ejemplo anterior, el atributo `salario` de la clase `Empleado` no será
|
||||
mostrado en las respuestas JSON y el problema estaría resuelto.
|
||||
|
||||
Sin embargo, puede haber algún otro endpoint de la API en el que necesitemos
|
||||
enviar el salario de los empleados en el JSON, en cuyo caso se tendrían problemas,
|
||||
ya que con la anotación `@JsonIgnore` tal atributo nunca se enviará en el JSON,
|
||||
y al eliminar la anotación se enviará el atributo siempre. Por lo tanto,
|
||||
se pierde la flexibilidad de controlar cuándo se deben enviar ciertos atributos
|
||||
en el JSON y cuándo no.
|
||||
|
||||
#### DTO
|
||||
|
||||
El patrón **DTO** (***Data Transfer Object***) es un patrón arquitectónico que
|
||||
se usó ampliamente en aplicaciones Java distribuidas (arquitectura
|
||||
cliente/servidor) para representar los datos que eran enviados y recibidos entre
|
||||
aplicaciones cliente y servidor.
|
||||
|
||||
El patrón **DTO** puede (y debe) usarse cuando no queremos exponer todos los
|
||||
atributos de alguna entidad en nuestro proyecto, una situación similar a los
|
||||
salarios de los empleados que discutimos anteriormente. Además, con la
|
||||
flexibilidad y la opción de filtrar qué datos se transmiten, podemos ahorrar
|
||||
tiempo de procesamiento.
|
||||
|
||||
#### Bucle infinito que causa StackOverflowError
|
||||
|
||||
Otro problema muy recurrente cuando se trabaja directamente con entidades JPA
|
||||
ocurre cuando una entidad tiene alguna *auto-relación* o *relación
|
||||
bidireccional*. Por ejemplo, considere las siguientes entidades JPA:
|
||||
|
||||
```java
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
@Entity(name = "Producto")
|
||||
@Table(name = "productos")
|
||||
public class Producto {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String nombre;
|
||||
private String descripcion;
|
||||
private BigDecimal precio;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = “id_categoria”)
|
||||
private Categoria categoria;
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = "id")
|
||||
@Entity(name = "Categoria")
|
||||
@Table(name = "categorias")
|
||||
public class Categoria {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String nombre;
|
||||
|
||||
@OneToMany(mappedBy = “categoria”)
|
||||
private List<Producto> productos = new ArrayList<>();
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Al devolver un objeto de tipo `Producto` en el Controller, Spring tendría
|
||||
problemas para generar el JSON de este objeto, lo que provocaría una excepción
|
||||
de tipo `StackOverflowError`. Este problema ocurre porque el objeto producto
|
||||
tiene un atributo de tipo `Categoria`, que a su vez tiene un atributo de tipo
|
||||
`Lista<Producto>` lo que provoca un bucle infinito en el proceso de serialización
|
||||
a JSON.
|
||||
|
||||
Este problema se puede resolver usando la anotación `@JsonIgnore` o usando las
|
||||
anotaciones `@JsonBackReference` y `@JsonManagedReference`, pero también se puede
|
||||
evitar usando un DTO que represente solo los datos que se deben devolver en el
|
||||
JSON.
|
||||
|
||||
### Paginación y Orden
|
||||
|
||||
Para la paginación se utiliza la interfase `Pageable`
|
||||
|
||||
```java
|
||||
...
|
||||
@GetMapping
|
||||
public Page<DatosListadoMedicos> listadoMedicos(
|
||||
@PageableDefault(size = 5) Pageable paginacion
|
||||
) {
|
||||
return medicoRepository.findAll(paginacion).map(DatosListadoMedicos::new);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Estos pueden pre-establecerse con la anotación `@PageableDefault`, o en el archivo
|
||||
[application.properties](./api_rest/api/src/main/resources/application.properties)
|
||||
|
||||
```ini
|
||||
spring.data.web.pageable.page-parameter=0
|
||||
spring.data.web.pageable.size-parameter=5
|
||||
spring.data.web.sort.sort-parameter=nombre
|
||||
```
|
||||
|
||||
Estos además pueden ser sobrescritos al hacer el request:
|
||||
|
||||
```http
|
||||
http://127.0.0.1:8080/medicos?size=3&page=2&sort=documento,desc
|
||||
```
|
||||
|
||||
#### Ver y formatear querys en el IDE
|
||||
|
||||
En archivo [application.properties](./api_rest/api/src/main/resources/application.properties)
|
||||
|
||||
```ini
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user