diff --git a/docker-compose.debug.yml b/docker-compose.debug.yml new file mode 100644 index 0000000000000000000000000000000000000000..f5add9a3ada6abcfb2b5f60e7f85dc6fa41cc657 --- /dev/null +++ b/docker-compose.debug.yml @@ -0,0 +1,13 @@ +version: '3.4' + +services: + users: + image: users + build: + context: . + dockerfile: ./Dockerfile + environment: + JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005,quiet=y + ports: + - 8080:8080 + - 5005:5005 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..bd82a266c21c855dea3774a48a49563f3d1630fa --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,41 @@ +version: '3.7' + +volumes: + kong_data: {} + users_data: {} + +networks: # Red interna para comunicar los servicios + kong-net: {} + +services: + Vinos-API: + image: tiendavinos-api-image + build: + context: . + dockerfile: ./Dockerfile + restart: unless-stopped + ports: + - "8080:8080" + networks: + - kong-net + environment: + SPRING_DATASOURCE_URL: jdbc:mysql://TiendaVinos-database:3306/TiendaVinos?createDatabaseIfNotExist=true + depends_on: + - TiendaVinos-database + + TiendaVinos-database: + image: mysql + hostname: TiendaVinos-database + cap_add: + - SYS_NICE + restart: unless-stopped + ports: + - "3307:3306" + networks: + - kong-net + volumes: + - users_data:/var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: TiendaVinos + MYSQL_ROOT_HOST: '%' diff --git a/pom.xml b/pom.xml index 3e14af79b6483148ae556fc1629daaf1da65ca44..4a5105f40fb646475876c237501ef5c99ea9c9c9 100644 --- a/pom.xml +++ b/pom.xml @@ -30,22 +30,26 @@ <java.version>17</java.version> </properties> <dependencies> - <!-- + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <optional>true</optional> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> - </dependency>--> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> -<!-- + <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> - </dependency>--> + </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> diff --git a/src/main/java/com/uva/users/Controller/ControllerVinos.java b/src/main/java/com/uva/users/Controller/ControllerVinos.java new file mode 100644 index 0000000000000000000000000000000000000000..99b473c9dbf556ffd909e1d583ab704f1f168593 --- /dev/null +++ b/src/main/java/com/uva/users/Controller/ControllerVinos.java @@ -0,0 +1,171 @@ +package com.uva.users.Controller; + +import org.springframework.boot.configurationprocessor.json.JSONObject; +import org.springframework.web.bind.annotation.*; + +import com.uva.users.Exception.BodegaException; +import com.uva.users.Exception.VinoException; +import com.uva.users.Model.Bodega; +import com.uva.users.Model.Vino; +import com.uva.users.Model.VinoConRelacion; +import com.uva.users.Repository.BodegaRepository; +import com.uva.users.Repository.VinoConRelacionRepository; +import com.uva.users.Repository.VinoRepository; + +import java.util.*; + +@RestController +@RequestMapping("/ejemploVinos") +public class ControllerVinos { + private final VinoRepository repository; + private final VinoConRelacionRepository repository2; + private final BodegaRepository repository3; + + ControllerVinos(VinoRepository repository, VinoConRelacionRepository repository2, BodegaRepository repository3) { + this.repository = repository; + this.repository2 = repository2; + this.repository3 = repository3; + } + + @GetMapping() + public List<Vino> getVinos() { + return repository.findAll(); + } + + @PutMapping("/{id}") + public String putVinos(@RequestBody String body, @PathVariable("id") Long identificador) { + return "Realizada operación Put. Con Id: " + identificador + ". Contenido del cuerpo de la petición: " + body; + } + + @PostMapping("/vinos") + public String postVinos(@RequestBody String body) { + return "Post: " + body; + } + + @DeleteMapping("/vinos") + public String deleteVinos(@RequestBody String body) { + return "Delete: " + body; + } + + @GetMapping("/vinos/{id}/{tipo}") + public String getVino(@PathVariable Long id, @PathVariable String tipo) { + return "ID del vino: " + id + ", Tipo de vino: " + tipo; + } + + @GetMapping("/cartaVinos") + public String getCartaConQuery(@RequestParam String nombre) { + return "Nombre del vino: " + nombre; + } + + @GetMapping("/informacion/{id}") + public String getVinoInfo(@PathVariable Long id, + @RequestParam(required = false, defaultValue = "precio") List<String> campos) { + String precio = "10.99"; + String denominacion = "Reserva"; + String bodega = "Abadia Retuerta"; + StringBuilder respuesta = new StringBuilder("ID del vino: " + id + ", Campos solicitados: "); + + for (String campo : campos) { + switch (campo) { + case "precio": + respuesta.append("precio: ").append(precio).append("; "); + break; + case "denominacion": + respuesta.append("denominación: ").append(denominacion).append("; "); + break; + case "bodega": + respuesta.append("bodega: ").append(bodega).append("; "); + break; + default: + respuesta.append(campo).append(": no disponible; "); + } + } + return respuesta.toString(); + } + + @PostMapping("/newVino") + public String newVino(@RequestBody Vino newVino) { + try { + repository.save(newVino); + return "Nuevo registro creado"; + } catch (Exception e) { + throw new VinoException("Error al crear el nuevo registro."); + } + } + + @GetMapping("/VinoPorNombre/{nombre}") + public Vino getVinoPorNombre_Comercial(@PathVariable String nombre) { + Vino vino = repository.findByNombreComercial(nombre) + .orElseThrow(() -> new VinoException("no se ha encontrado el vino de nombre " + nombre)); + return vino; + } + + @GetMapping("/VinoPorPrecio") + public List<Vino> getVinoPorPrecio(@RequestParam Float precio1, @RequestParam Float precio2) { + List<Vino> vinos = repository.findByPrecioBetween(precio1, precio2); + return vinos; + } + + @DeleteMapping("/BorrarPorDenominacion_Categoria") + public List<Vino> deletePorDenominacion_Categoria(@RequestBody String json) { + try { + JSONObject jsonObjeto = new JSONObject(json); + String denominacion = jsonObjeto.getString("denominacion"); + String categoria = jsonObjeto.getString("categoria"); + boolean existe = repository.existsVinoByDenominacionAndCategoria(denominacion, categoria); + if (existe) { + List<Vino> borrados = repository.deleteByDenominacionAndCategoria(denominacion, categoria); + return borrados; + } else { + System.out.println("No existen vinos de la categorÃa y denominación"); + } + } catch (Exception e) { + System.out.println(e); + return null; + } + return null; + } + + @GetMapping("/VinoPorDenominacionOrdenadoPorNombre/{denominacion}") + public List<Vino> getVinoPorDenominacionOrdenado(@PathVariable String denominacion) { + List<Vino> vinos = repository.findByDenominacionOrdenadoNombreDesc(denominacion); + return vinos; + } + + @GetMapping("/VinoPorDenominacionYCategoria") + public List<Vino> getVinoPorDenominacionYCategoria(@RequestParam String denominacion, + @RequestParam String categoria) { + List<Vino> vinos = repository.findByDenominacionYCategoria(denominacion, categoria); + return vinos; + } + + @PostMapping("/newBodega") + public String newBodega(@RequestBody Bodega newBodega) { + try { + repository3.save(newBodega); + return "Nuevo registro creado"; + } catch (Exception e) { + throw new BodegaException("Error al crear el nuevo registro."); + } + } + + @PostMapping("/newVinoConRelacion") + public String newVinoConRelacion(@RequestBody VinoConRelacion newVinoConRelacion) { + try { + repository2.save(newVinoConRelacion); + return "Nuevo registro creado"; + } catch (Exception e) { + throw new VinoException("Error al crear el nuevo registro."); + } + } + + @GetMapping(value = "/getBodega/{id}", produces = "application/json") + public Optional<Bodega> getBodega(@PathVariable Integer id) { + return repository3.findById(id); + } + + @GetMapping(value = "/getVinoConRelacion/{id}", produces = "application/json") + public Optional<VinoConRelacion> getVinoConRelacion(@PathVariable Integer id) { + return repository2.findById(id); + } +} diff --git a/src/main/java/com/uva/users/Exception/BodegaException.java b/src/main/java/com/uva/users/Exception/BodegaException.java new file mode 100644 index 0000000000000000000000000000000000000000..2c769122cab9a21b6e5f77d217015774ca3576f3 --- /dev/null +++ b/src/main/java/com/uva/users/Exception/BodegaException.java @@ -0,0 +1,11 @@ +package com.uva.users.Exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.UNPROCESSABLE_ENTITY) +public class BodegaException extends RuntimeException { + public BodegaException(String mensaje) { + super(mensaje); + } +} \ No newline at end of file diff --git a/src/main/java/com/uva/users/Exception/VinoException.java b/src/main/java/com/uva/users/Exception/VinoException.java new file mode 100644 index 0000000000000000000000000000000000000000..c84304025170982f77a2520c961cec77b90101a9 --- /dev/null +++ b/src/main/java/com/uva/users/Exception/VinoException.java @@ -0,0 +1,11 @@ +package com.uva.users.Exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.UNPROCESSABLE_ENTITY) +public class VinoException extends RuntimeException { + public VinoException(String mensaje) { + super(mensaje); + } +} diff --git a/src/main/java/com/uva/users/Model/Bodega.java b/src/main/java/com/uva/users/Model/Bodega.java new file mode 100644 index 0000000000000000000000000000000000000000..59c7d142fc3225f3f15050b5106589d03537b216 --- /dev/null +++ b/src/main/java/com/uva/users/Model/Bodega.java @@ -0,0 +1,79 @@ +package com.uva.users.Model; + +import java.util.List; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import jakarta.persistence.Basic; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +@Entity +@Table(name = "bodega") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") +public class Bodega { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Basic(optional = false) + @Column(name = "ID") + private Integer id; + + @Basic(optional = false) + @Column(name = "NOMBRE") + private String nombre; + @Basic(optional = false) + @Column(name = "CIF") + private String cif; + @Basic(optional = false) + @Column(name = "DIRECCION") + private String direccion; + @OneToMany(mappedBy = "bodegaId", fetch = FetchType.EAGER, cascade = CascadeType.MERGE) + private List<VinoConRelacion> vinoCollection; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public String getCif() { + return cif; + } + + public void setCif(String cif) { + this.cif = cif; + } + + public String getDireccion() { + return direccion; + } + + public void setDireccion(String direccion) { + this.direccion = direccion; + } + + public List<VinoConRelacion> getVinoCollection() { + return vinoCollection; + } + + public void setVinoCollection(List<VinoConRelacion> vinoCollection) { + this.vinoCollection = vinoCollection; + } + +} diff --git a/src/main/java/com/uva/users/Model/Vino.java b/src/main/java/com/uva/users/Model/Vino.java new file mode 100644 index 0000000000000000000000000000000000000000..dd0ae392ca3ec056c684d2ff70d1145f2248db86 --- /dev/null +++ b/src/main/java/com/uva/users/Model/Vino.java @@ -0,0 +1,94 @@ +package com.uva.users.Model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.NamedQueries; +import jakarta.persistence.NamedQuery; +import java.io.Serializable; + +@Entity +@Table(name = "Vino") +@NamedQueries({ + @NamedQuery( + name = "Vino.findByDenominacionOrdenadoNombreDesc", + query = "SELECT V FROM Vino V WHERE V.denominacion = ?1 ORDER BY V.nombreComercial DESC"), + @NamedQuery( + name = "Vino.findByDenominacionYCategoria", + query = "SELECT V FROM Vino V WHERE V.denominacion = ?1 AND V.categoria = ?2" + ) +}) +public class Vino implements Serializable { + @Id + @GeneratedValue + private Integer Id; + @Column(name = "nombre_comercial") + private String nombreComercial; + private String denominacion; + private String categoria; + @Column(nullable = false) + private Float precio; + private Integer bodegaId; + + Vino() { + } + + Vino(String nombre_comercial, String denominacion, String categoria, Float precio, Integer bodega) { + this.nombreComercial = nombre_comercial; + this.denominacion = denominacion; + this.categoria = categoria; + this.precio = precio; + this.bodegaId = bodega; + } + + // Getters y Setters + public Integer getId() { + return Id; + } + + public void setId(Integer Id) { + this.Id = Id; + } + + public String getNombreComercial() { + return nombreComercial; + } + + public void setNombreComercial(String nombreComercial) { + this.nombreComercial = nombreComercial; + } + + public String getDenominacion() { + return denominacion; + } + + public void setDenominacion(String denominacion) { + this.denominacion = denominacion; + } + + public String getCategoria() { + return categoria; + } + + public void setCategoria(String categoria) { + this.categoria = categoria; + } + + public Float getPrecio() { + return precio; + } + + public void setPrecio(Float precio) { + this.precio = precio; + } + + public Integer getBodegaId() { + return bodegaId; + } + + public void setBodegaId(Integer bodegaId) { + this.bodegaId = bodegaId; + } +} \ No newline at end of file diff --git a/src/main/java/com/uva/users/Model/VinoConRelacion.java b/src/main/java/com/uva/users/Model/VinoConRelacion.java new file mode 100644 index 0000000000000000000000000000000000000000..3c8833a6dcf0a1c1acf65eb0f93010782a76632a --- /dev/null +++ b/src/main/java/com/uva/users/Model/VinoConRelacion.java @@ -0,0 +1,113 @@ +package com.uva.users.Model; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Table; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; + +@Entity +@Table(name = "VinoConRelacion") +@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") +public class VinoConRelacion { + @Id + @GeneratedValue + private Integer Id; + // @Size(max = 50) // si no se pone esta anotación lo creo por defecto con + // size=255 + @Column(name = "nombre_comercial") + private String nombreComercial; + // @Size(max = 30) + private String denominacion; + // @Size(max = 30) + private String categoria; + @Column(nullable = false) + private Float precio; + + @JoinColumn(name = "Bodega_Id", referencedColumnName = "ID") + + @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.MERGE) + private Bodega bodegaId; + + VinoConRelacion() { + } + + VinoConRelacion(String nombre_comercial, String denominacion, String categoria, Float precio, Bodega bodega) { + this.nombreComercial = nombre_comercial; + this.denominacion = denominacion; + this.categoria = categoria; + this.precio = precio; + this.bodegaId = bodega; + } + + public String getNombreComercial() { + return nombreComercial; + } + + public void setNombreComercial(String nombreComercial) { + this.nombreComercial = nombreComercial; + } + + public Bodega getBodegaId() { + return bodegaId; + } + + public void setBodegaId(Bodega bodegaId) { + this.bodegaId = bodegaId; + } + + public Integer getId() { + return Id; + } + + public void setId(Integer id) { + Id = id; + } + + public String getNombre_comercial() { + return nombreComercial; + } + + public void setNombre_comercial(String nombre_comercial) { + this.nombreComercial = nombre_comercial; + } + + public String getDenominacion() { + return denominacion; + } + + public void setDenominacion(String denominacion) { + this.denominacion = denominacion; + } + + public String getCategoria() { + return categoria; + } + + public void setCategoria(String categoria) { + this.categoria = categoria; + } + + public Float getPrecio() { + return precio; + } + + public void setPrecio(Float precio) { + this.precio = precio; + } + + public Bodega getBodega_id() { + return bodegaId; + } + + public void setBodega_id(Bodega bodegaId) { + this.bodegaId = bodegaId; + } + +} \ No newline at end of file diff --git a/src/main/java/com/uva/users/MyConfiguration.java b/src/main/java/com/uva/users/MyConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..0340723b2af69364add9db453f9672df12d5e655 --- /dev/null +++ b/src/main/java/com/uva/users/MyConfiguration.java @@ -0,0 +1,15 @@ +package com.uva.users; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class MyConfiguration implements WebMvcConfigurer { + + @SuppressWarnings("null") + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } +} \ No newline at end of file diff --git a/src/main/java/com/uva/users/Repository/BodegaRepository.java b/src/main/java/com/uva/users/Repository/BodegaRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..de92b0f67ce8e3f3175240f1b7722852a00b42d3 --- /dev/null +++ b/src/main/java/com/uva/users/Repository/BodegaRepository.java @@ -0,0 +1,7 @@ +package com.uva.users.Repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import com.uva.users.Model.Bodega; + +public interface BodegaRepository extends JpaRepository<Bodega, Integer> { +} diff --git a/src/main/java/com/uva/users/Repository/VinoConRelacionRepository.java b/src/main/java/com/uva/users/Repository/VinoConRelacionRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..2f3d8076252b8582bb51ea5b1ec9345490490105 --- /dev/null +++ b/src/main/java/com/uva/users/Repository/VinoConRelacionRepository.java @@ -0,0 +1,7 @@ +package com.uva.users.Repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import com.uva.users.Model.VinoConRelacion; + +public interface VinoConRelacionRepository extends JpaRepository<VinoConRelacion, Integer> { +} diff --git a/src/main/java/com/uva/users/Repository/VinoRepository.java b/src/main/java/com/uva/users/Repository/VinoRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..14d4bd32ff1e12cf5374280500dea8db1a6b2c67 --- /dev/null +++ b/src/main/java/com/uva/users/Repository/VinoRepository.java @@ -0,0 +1,23 @@ +package com.uva.users.Repository; + +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import com.uva.users.Model.Vino; +import jakarta.transaction.Transactional; + +public interface VinoRepository extends JpaRepository<Vino, Integer> { + Optional<Vino> findByNombreComercial(String nombre); + + List<Vino> findByPrecioBetween(Float precio1, Float precio2); + + boolean existsVinoByDenominacionAndCategoria(String denomiacion, String categoria); + + @Transactional + // Long deleteByDenominacionAndCategoria(String denominacion, String categoria); + List<Vino> deleteByDenominacionAndCategoria(String denominacion, String categoria); + + List<Vino> findByDenominacionOrdenadoNombreDesc(String denominacion); + + List<Vino> findByDenominacionYCategoria(String denominacion, String categoria); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 79dd98c671232c704338cb41fad2ce1a8605f0d3..8dbf04327fceec2e914de8b02a151f549ded295e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,7 @@ spring.application.name=users +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect +spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/TiendaVinos?createDatabaseIfNotExist=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver \ No newline at end of file