Mauricio José Toledo Solares
Consejo sano del curso: cada video compilen y corran su codigo.
¿Cómo crear la implementación de nuestro repositorio compra?
Para implementar un repositorio que interactúe con la base de datos en relación a las compras, primero es necesario crear la clase CompraRepository, que implementará el PurchaseRepository. Asegúrate de anotar esta clase como @Repository para que Spring la reconozca como un componente o bean necesario para la comunicación con la base de datos. Entonces, ¿cómo empezamos?
Pasos iniciales para crear el repositorio
CompraRepository:
persistence, crea una nueva clase Java llamada CompraRepository.PurchaseRepository.@Repository para que Spring la identifique correctamente.CrudRepository llamada CompraCrudRepository.Interacción con la base de datos
Para poder interactuar adecuadamente, el CompraCrudRepository debe extender de CrudRepository y recibir como parámetros la entidad Compra y su clave primaria, que en este caso es un Integer.
public interface CompraCrudRepository extends CrudRepository<Compra, Integer> { // Métodos adicionales según el caso }
Luego, debes inyectar esta interfaz en tu CompraRepository junto al mapper necesario:
@Autowired private CompraCrudRepository compraCrudRepository; @Autowired private PurchaseMapper purchaseMapper;
Implementación de métodos fundamentales
Método getAll
El método getAll recupera todos los registros de compras y los convierte a objetos del dominio:
public List<Purchase> getAll() { List<Compra> compras = (List<Compra>) compraCrudRepository.findAll(); return purchaseMapper.toPurchases(compras); }
Método getByClient
Para recuperar compras por cliente, es necesario crear un query método dentro del CompraCrudRepository:
Optional<List<Compra>> findByClienteId(String clientId);
Y emplearlo dentro de CompraRepository:
public Optional<List<Purchase>> getByClient(String clientId) { return compraCrudRepository.findByClienteId(clientId) .map(compras -> purchaseMapper.toPurchases(compras)); }
Guardado en cascada
Para garantizar que la información se guarde en cascada, asegúrate de que la entidad Compra conozca sus productos y viceversa. Implementa el patrón de relaciones cascade y mappedBy en las entidades correspondientes.
@OneToMany(mappedBy = "compra", cascade = CascadeType.ALL) private List<Producto> productos;
Configura la relación en la entidad CompraProducto para que los productos puedan asociarse correctamente a una compra.
Método save
public Purchase save(Purchase purchase) { Compra compra = purchaseMapper.toCompra(purchase); compra.getProductos().forEach(producto -> producto.setCompra(compra)); return purchaseMapper.toPurchase(compraCrudRepository.save(compra)); }
¿Qué sigue después de implementar el repositorio?
Este tutorial se centra en la implementación del repositorio, pero recuerda que aún faltan los servicios y controladores para completar la capa de negocio y presentación. Te animo a desarrollar estos componentes adicionales y compartir tus resultados. Si enfrentas problemas, recuerda que siempre puedes buscar soluciones en el sistema de archivos del curso o las discusiones comunitarias. ¡Sigue adelante con tu aprendizaje!
Mauricio José Toledo Solares
Consejo sano del curso: cada video compilen y corran su codigo.
David Gallego
Edward Camilo Martinez Frias
Estuvo densa esta clase, me dejo un poco loco la cantidad de vueltas que se da con las relaciones entre las clases y las relaciones de los mapper y las entidades 😵💫.
Geyson Jair Rangel Ortega
de acuerdo. Se dan por sobreentendidos muchos temas muy importantes y complejos pero se detienen a explicar cosas bàsicas en las que no se deberìa profundizar. Serìa muy bueno explicar mas a detalle las relaciones entre el dominio y el Repository
Erik Sigcha
Me parece que el video de esta clase esta diferente del audio
KARINA DAVILA
Confirmo
Miguel Torres
Hola, @eriksigcha y @karinadavila😄
Están en lo correcto. El video es de la clase anterior, pero el audio de esta. Vamos a corregirlo. 🙌💚
Cristian Felipe Patiño Cáceres
En mi caso la petición de compras me sacaba error debido a que me indicaba que no era posible convertir el numero de celular por un entero, para esto tuve que cambiar el atributo celular de la entidad Cliente a Long y ya me funciono :)
Mauricio Hoyos
Hola Cristian, supongo que el error era porque un numero de cel puede desbordar la cantidad de bits que soporta un dato de tipo entero, por buena practicas es mejor usar String para datos que no requieren cálculos matemáticos, teléfonos, número de cédula, etc.
DIEGO ALONSO ARCHILA TORRES
Así como indica Mauricio, solo guarda datos numéricos si vas a hacer cálculos con ellos, de otra manera es mejor el String.
Jose Sanchez
Si les arroja un error al momento de trabajar con la funcion save, específicamente al llamar a getProductos() y en setCompra(compra), es necesario generar los getters y setters en las clases Compras y ComprasProducto.
Javier Mauricio Torres Vargas
Estas claes van a mil, como cuando los productores de una serie quieren acabarla inmediatamente, y meten todo en unos pocos capitulos.
Magdiel Linares
😂
Alejandro Tangarife Rivas
A la hora de generar los controllers, y dar respuestas HTTP Es buena práctica generar 2 posibles respuestas (Efectiva - Negativa) con Try Catch. Así:
@GetMapping("/") public ResponseEntity<List<Purchase>> getAll() { try { return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK); } catch (RuntimeException ex) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); } }
Algo así... De esta manera nos estamos asegurando que en caso de no encontrar respuesta o encontrar respuestas sin contenido podamos manejar errores y mostrarlos en pantalla de una forma más específica y controlada; si me equivoco por favor no duden en corregirme jajaj.
Nicoll Idaly Angulo Mejia
No entendi, la parte de cascadas
Jose Alexis Vazquez Morales
significa que todas las entidades que dependen de una entidad que utiliza cascada se veran afectadas si se elimina o actualiza la propiedad que esta relacionada con otras entidades.
Jose Alexis Vazquez Morales
por ejemplo si tenemos una entidad Servicio en la que uno de sus atributos contiene una relacion de muchos a uno con una entidad Mecanico, si a ese atributo le indicamos que tenga un comportamiento de cascada, si actualizamos la propiedad Mecanico de Servicios, la entidad Mecanico se vera afectada.
uRieL Martinez Bautista
Es mejor injeccion por constructor que por @autowired.
Fabian Camilo Herrera Ramirez
es necesario el @mapsid, no es suficiente con el join column que ya especifca como se resuelve la relacion?
Alejandro Ramírez
ProfesorCuando queremos guardar en cascada debemos poner la anotación @MapsId porque esta anotación es la que proporciona la asignación para una clave primaria cuando se usa @EmbeddedId. La anotación @JoinColumn solo especifica que columna se relaciona a la hora trabajar con el atributo de la relación.
Rosemberg Porras Mancilla
Pero en ese caso, cuando se quiere hacer la persistencia del objeto ComprasProducto, el mapper solo guardó en el ComprasProductoPK, el id del producto, y el id de la compra la dejo "null", y para complementar esto, es que se hace el for each para llenar el objeto Compra, en Compra Producto
compra.getProductos().forEach(producto -> producto.setCompra(compra));
Si en vez de hacer eso, simplemente llenaramos completamente el objeto de ComprasProductoPK con el id de la compra, no habria la necesidad de hacer lo del maps id cierto? que es el caso de cuando se persiste un producto, que no se le pasa el objeto category si no la category id y luego cuando se le hace get, esto ya hace el mapeo y devuelve la category
Carlos Ivan Franco Felmenal
Siento que está fue la clase mas enredada de todas
William Alexander Hernandez Leiva
Mauricio José Toledo Solares
Error: Could not read entity state from ResultSet EntityKey[] with root cause spring.
Causa: El celular de la entidad Cliente estaba como integer y lo cambie a long.
Jhon Eduard Bocanegra Ortiz
¿Como seria la peticion en postman para guardar una compra, estoy tratando pero me sale bad request 400?
Daniel Fernando Franco Beltrán
Hola Jhon, ¿cómo está realizando la petición? Según el error, el problema está en que no se está construyendo apropiadamente la petición.
Marco Guaman
seleccionar el metodo POST y colocar el json en body
Olga Isela Ceballos Miranda
Alguien que me pueda explicar un poco más a profundidad la annotation @MapsId Gracias!!
Cristhian Andres vargas cuero
En otra nota el profesor le preguntan algo relacionado con @MapsId y el responde:
Cuando queremos guardar en cascada debemos poner la anotación @MapsId porque esta anotación es la que proporciona la asignación para una clave primaria cuando se usa @EmbeddedId.
La anotación @JoinColumn solo especifica que columna se relaciona a la hora trabajar con el atributo de la relación.
Luis Pavez León
Otra forma de verlo podría ser: Se usa @MapsId para que al guardar en Cascada "cada objeto" de ComprasProducto, se copie desde el objeto principal (Compra), el campo anotado con el @Id (idCompra), y se guarde este valor en el campo "idCompra" de ComprasProductoPK (clave embebida o compuesta de ComprasProducto).
Junior Andres González Caraballo
Honestamente, no me están gustando esta serie de spring. No corre el código, y solo escribe, con frecuencia las explicaciones son superficiales y sigue avanzando sin consolidar los conocimientos con ejemplos prácticos.
Fredy Orlando Garcia Mojica
Que vuelta tan enredada con esas relaciones y conversiones, RECOMENDACIÓN: Verificar que se tengan todos los getter an setter de las clases en las que aplique.
Carlos Jose Hernandez Candray
Comparto enlace donde explican diferentes usos de @mapsId:
https://ajaxhispano.com/ask/puede-alguien-explicarme-mapsid-en-hibernacion-62818/
@Service public class PurchaseService { @Autowired private PurchaseRepository purchaseRepository; public List<Purchase> getAll() { return purchaseRepository.getAll(); } public Optional<List<Purchase>> getByClient(String clientId) { return purchaseRepository.getByClient(clientId); } public Purchase save(Purchase purchase) { return purchaseRepository.save(purchase); } } @RestController @RequestMapping("/purchases") public class PurchaseController { @Autowired private PurchaseService purchaseService; @GetMapping("/all") public ResponseEntity<List<Purchase>> getAll() { return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK); } @GetMapping("/client/{idClient}") public ResponseEntity<List<Purchase>> getByClient(@PathVariable("idClient") String clientId) { return purchaseService.getByClient(clientId) .map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK)) .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND)); } @PostMapping("/save") public ResponseEntity<Purchase> save(@RequestBody Purchase purchase) { return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.CREATED); } }
Comparto mi código del servicio y controlador.
@Service public class PurchaseService { @Autowired private PurchaseRepository purchaseRepository; /** * Metodo para listar las compras. * * @return Lista de compras */ public List<Purchase> getAll(){ return purchaseRepository.getAll(); } /** * Metodo para buscar las compras de un cliente * * @param clientId Identificador del cliente de tipo String * @return las compras del cliente */ public Optional<List<Purchase>> getByClient(String clientId){ return purchaseRepository.getByClient(clientId); } /** * Metodo para guardar una compra * * @param purchase Entity de Purchase * @return */ public Purchase save(Purchase purchase){ return purchaseRepository.save(purchase); } }
@RestController @RequestMapping(value = "/purchases") public class PurchaseController {
@Autowired private PurchaseService purchaseService; @GetMapping(value = "/all") public ResponseEntity<List<Purchase>> getAll(){ return new ResponseEntity<>(purchaseService.getAll(), HttpStatus.OK); } @GetMapping(value = "/{clientId}") public ResponseEntity<List<Purchase>> getByClient(@PathVariable String clientId){ return purchaseService.getByClient(clientId) .map(purchases -> new ResponseEntity<>(purchases, HttpStatus.OK)) .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND)); } @PostMapping(value = "/save") public ResponseEntity<Purchase> save(@RequestBody Purchase purchase){ return new ResponseEntity<>(purchaseService.save(purchase), HttpStatus.OK); }
}```