Commit inicial
This commit is contained in:
commit
5de37d63bb
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/bin/
|
||||
*.class
|
||||
/target/
|
||||
# Eclipse
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
4
README.md
Normal file
4
README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Repositorio para el examen de ORDINARIA de Ampliación de Entornos (RA3-RA4-RA5).
|
||||
|
||||
¡Ánimo y a por ello!
|
||||
|
||||
68
pom.xml
Normal file
68
pom.xml
Normal file
@ -0,0 +1,68 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.lapaloma.examen.aaee</groupId>
|
||||
<artifactId>aaee_gobierno</artifactId>
|
||||
<version>0.0.2</version>
|
||||
|
||||
<name>Prueba de Springboot</name>
|
||||
<description>Proyecto para poder probar el funcionamiento de SpringBoot</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>4.0.1</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>23</java.version>
|
||||
<junit.version>6.0.3</junit.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- JDBC starter: activa DataSource y HikariCP -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Starter test: incluye JUnit 5, Mockito, AssertJ, etc -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Source: https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>9.7.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
13
src/main/java/org/lapaloma/examen/aaee/AppGesconSB.java
Normal file
13
src/main/java/org/lapaloma/examen/aaee/AppGesconSB.java
Normal file
@ -0,0 +1,13 @@
|
||||
package org.lapaloma.examen.aaee;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class AppGesconSB {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AppGesconSB.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package org.lapaloma.examen.aaee.controller;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.lapaloma.examen.aaee.service.CocheService;
|
||||
import org.lapaloma.examen.aaee.vo.Coche;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/coches")
|
||||
public class CocheController {
|
||||
|
||||
private final CocheService cocheService;
|
||||
|
||||
public CocheController(CocheService cocheService) {
|
||||
this.cocheService = cocheService;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<Coche> consultarCochesPorMarca(@RequestParam(required = false) String marca) {
|
||||
return cocheService.consultarCochesPorMarca(marca);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Coche> crearNuevoCoche(@Valid @RequestBody Coche coche) {
|
||||
Coche creado = cocheService.crearNuevoCoche(coche);
|
||||
URI location = URI.create("/coches/" + creado.getId());
|
||||
return ResponseEntity.created(location).body(creado);
|
||||
}
|
||||
|
||||
}
|
||||
11
src/main/java/org/lapaloma/examen/aaee/dao/ICocheDAO.java
Normal file
11
src/main/java/org/lapaloma/examen/aaee/dao/ICocheDAO.java
Normal file
@ -0,0 +1,11 @@
|
||||
package org.lapaloma.examen.aaee.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.lapaloma.examen.aaee.vo.Coche;
|
||||
|
||||
public interface ICocheDAO {
|
||||
List<Coche> obtenerCochesPorMarca(String marca);
|
||||
|
||||
Coche crearCoche(Coche coche);
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package org.lapaloma.examen.aaee.dao.impl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.lapaloma.examen.aaee.dao.ICocheDAO;
|
||||
import org.lapaloma.examen.aaee.vo.Coche;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class CocheDaoJDBC implements ICocheDAO {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
public CocheDaoJDBC(DataSource dataSource) {
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Coche> obtenerCochesPorMarca(String marca) {
|
||||
List<Coche> lista = new ArrayList<>();
|
||||
|
||||
String sqlAll = "SELECT id, marca, modelo, cilindrada FROM coche";
|
||||
String sqlByMarca = "SELECT id, marca, modelo, cilindrada FROM coche WHERE LOWER(marca) = LOWER(?)";
|
||||
|
||||
try (Connection conexion = dataSource.getConnection();
|
||||
PreparedStatement ps = (marca == null || marca.isBlank()) ? conexion.prepareStatement(sqlAll)
|
||||
: conexion.prepareStatement(sqlByMarca);) {
|
||||
|
||||
if (marca != null && !marca.isBlank()) {
|
||||
ps.setString(1, marca);
|
||||
}
|
||||
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
Coche c = new Coche();
|
||||
c.setId(rs.getInt("id"));
|
||||
c.setMarca(rs.getString("marca"));
|
||||
c.setModelo(rs.getString("modelo"));
|
||||
c.setCilindrada(rs.getInt("cilindrada"));
|
||||
lista.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return lista;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Coche crearCoche(Coche coche) {
|
||||
String insertSQL = "INSERT INTO coche (marca, modelo, cilindrada) VALUES (?, ?, ?)";
|
||||
|
||||
try (Connection conexion = dataSource.getConnection();
|
||||
PreparedStatement ps = conexion.prepareStatement(insertSQL, Statement.RETURN_GENERATED_KEYS);) {
|
||||
|
||||
ps.setString(1, coche.getMarca());
|
||||
ps.setString(2, coche.getModelo());
|
||||
ps.setInt(3, coche.getCilindrada());
|
||||
|
||||
int filas = ps.executeUpdate();
|
||||
if (filas == 0) {
|
||||
throw new SQLException("No se insertó el coche");
|
||||
}
|
||||
|
||||
try (ResultSet keys = ps.getGeneratedKeys()) {
|
||||
if (keys.next()) {
|
||||
coche.setId(keys.getInt(1));
|
||||
}
|
||||
}
|
||||
|
||||
return coche;
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Error al crear coche", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package org.lapaloma.examen.aaee.excepcion;
|
||||
|
||||
public class CocheNoEncontradoException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public CocheNoEncontradoException(String mensaje) {
|
||||
super(mensaje);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package org.lapaloma.examen.aaee.excepcion;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
|
||||
Map<String, String> errors = new HashMap<>();
|
||||
ex.getBindingResult().getFieldErrors().forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors);
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ResponseEntity<Map<String, String>> handleIllegalArgument(IllegalArgumentException ex) {
|
||||
Map<String, String> error = new HashMap<>();
|
||||
error.put("error", ex.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
|
||||
}
|
||||
|
||||
@ExceptionHandler(CocheNoEncontradoException.class)
|
||||
public ResponseEntity<Map<String, String>> handleNotFound(CocheNoEncontradoException ex) {
|
||||
Map<String, String> error = new HashMap<>();
|
||||
error.put("error", ex.getMessage());
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package org.lapaloma.examen.aaee.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.lapaloma.examen.aaee.dao.ICocheDAO;
|
||||
import org.lapaloma.examen.aaee.excepcion.CocheNoEncontradoException;
|
||||
import org.lapaloma.examen.aaee.vo.Coche;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class CocheService {
|
||||
|
||||
private final ICocheDAO cocheDAO;
|
||||
|
||||
public CocheService(ICocheDAO cocheDAO) {
|
||||
this.cocheDAO = cocheDAO;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public List<Coche> consultarCochesPorMarca(String marca) {
|
||||
return cocheDAO.obtenerCochesPorMarca(marca);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Coche crearNuevoCoche(Coche coche) {
|
||||
if (coche.getCilindrada() == null || coche.getCilindrada() <= 0) {
|
||||
throw new IllegalArgumentException("Cilindrada debe ser mayor que 0");
|
||||
}
|
||||
return cocheDAO.crearCoche(coche);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Coche obtenerPorId(Integer id) {
|
||||
return cocheRepository.findById(id).orElseThrow(() -> new CocheNoEncontradoException("Coche con id '" + id + "' no encontrado"));
|
||||
}
|
||||
}
|
||||
66
src/main/java/org/lapaloma/examen/aaee/vo/Coche.java
Normal file
66
src/main/java/org/lapaloma/examen/aaee/vo/Coche.java
Normal file
@ -0,0 +1,66 @@
|
||||
package org.lapaloma.examen.aaee.vo;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Positive;
|
||||
|
||||
public class Coche {
|
||||
|
||||
private Integer id;
|
||||
|
||||
@NotBlank(message = "Marca es obligatoria")
|
||||
private String marca;
|
||||
|
||||
@NotBlank(message = "Modelo es obligatorio")
|
||||
private String modelo;
|
||||
|
||||
@NotNull(message = "Cilindrada es obligatoria")
|
||||
@Positive(message = "Cilindrada debe ser mayor que 0")
|
||||
private Integer cilindrada;
|
||||
|
||||
public Coche() {}
|
||||
|
||||
public Coche(Integer id, String marca, String modelo, Integer cilindrada) {
|
||||
this.id = id;
|
||||
this.marca = marca;
|
||||
this.modelo = modelo;
|
||||
this.cilindrada = cilindrada;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getMarca() {
|
||||
return marca;
|
||||
}
|
||||
|
||||
public void setMarca(String marca) {
|
||||
this.marca = marca;
|
||||
}
|
||||
|
||||
public String getModelo() {
|
||||
return modelo;
|
||||
}
|
||||
|
||||
public void setModelo(String modelo) {
|
||||
this.modelo = modelo;
|
||||
}
|
||||
|
||||
public Integer getCilindrada() {
|
||||
return cilindrada;
|
||||
}
|
||||
|
||||
public void setCilindrada(Integer cilindrada) {
|
||||
this.cilindrada = cilindrada;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Coche [id=" + id + ", marca=" + marca + ", modelo=" + modelo + ", cilindrada=" + cilindrada + "]";
|
||||
}
|
||||
}
|
||||
15
src/main/resources/application.properties
Normal file
15
src/main/resources/application.properties
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
# Puerto en que escucha Spring Boot
|
||||
server.port=8080
|
||||
|
||||
# Servicio de la base de datos.
|
||||
# Ejemplo url base dator:
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://${DB_HOST:192.168.1.36}:${DB_PORT:3306}/${DB_NAME:Gobierno}
|
||||
spring.datasource.username=${DB_USER:root}
|
||||
spring.datasource.password=${DB_PASSWORD:mysql_123}
|
||||
|
||||
# Parámetros del Pool de conexiones HikariCP
|
||||
spring.datasource.hikari.maximum-pool-size=10
|
||||
spring.datasource.hikari.minimum-idle=2
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
package org.lapaloma.examen.aaee.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lapaloma.examen.aaee.dao.ICocheDAO;
|
||||
import org.lapaloma.examen.aaee.vo.Coche;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class CocheServiceTest {
|
||||
|
||||
@Mock
|
||||
private ICocheDAO cocheDAO;
|
||||
|
||||
@InjectMocks
|
||||
private CocheService cocheService;
|
||||
|
||||
@Test
|
||||
void consultarCochesPorMarca_marcaExistente_devuelveLista() {
|
||||
List<Coche> lista = Arrays.asList(
|
||||
new Coche(1, "Seat", "Ibiza", 1200),
|
||||
new Coche(2, "Seat", "Leon", 1400),
|
||||
new Coche(3, "Seat", "Toledo", 1600));
|
||||
|
||||
when(cocheDAO.obtenerCochesPorMarca("Seat")).thenReturn(lista);
|
||||
|
||||
List<Coche> resultado = cocheService.consultarCochesPorMarca("Seat");
|
||||
|
||||
assertEquals(3, resultado.size());
|
||||
verify(cocheDAO).obtenerCochesPorMarca("Seat");
|
||||
}
|
||||
|
||||
@Test
|
||||
void consultarCochesPorMarca_marcaInexistente_devuelveListaVacia() {
|
||||
when(cocheDAO.obtenerCochesPorMarca("Ferrari")).thenReturn(Collections.emptyList());
|
||||
|
||||
List<Coche> resultado = cocheService.consultarCochesPorMarca("Ferrari");
|
||||
|
||||
assertTrue(resultado.isEmpty());
|
||||
verify(cocheDAO).obtenerCochesPorMarca("Ferrari");
|
||||
}
|
||||
|
||||
@Test
|
||||
void crearNuevoCoche_cilindradaNula_lanzaIllegalArgumentException() {
|
||||
Coche coche = new Coche(null, "Volkswagen", "Golf", null);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> cocheService.crearNuevoCoche(coche));
|
||||
}
|
||||
|
||||
@Test
|
||||
void crearNuevoCoche_cilindradaNoPositiva_lanzaIllegalArgumentException() {
|
||||
Coche coche = new Coche(null, "Renault", "Clio", 0);
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> cocheService.crearNuevoCoche(coche));
|
||||
}
|
||||
|
||||
@Test
|
||||
void crearNuevoCoche_datosValidos_devuelveCocheCreado() {
|
||||
Coche entrada = new Coche(null, "Volkswagen", "Golf", 2000);
|
||||
Coche creado = new Coche(10, "Volkswagen", "Golf", 2000);
|
||||
|
||||
when(cocheDAO.crearCoche(entrada)).thenReturn(creado);
|
||||
|
||||
Coche resultado = cocheService.crearNuevoCoche(entrada);
|
||||
|
||||
assertNotNull(resultado);
|
||||
assertEquals(creado.getId(), resultado.getId());
|
||||
verify(cocheDAO).crearCoche(entrada);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user