Clase de Repositorio de Productos con Spring Framework
Resumen
¿Cómo interactuar con la base de datos usando Spring?
Para manejar eficientemente la interacción con tus bases de datos en aplicaciones Spring, es fundamental comprender cómo usar los repositorios, los métodos CRUD y las anotaciones adecuadas. En esta guía, te mostramos cómo estructurar y trabajar con un repositorio de productos, desde consultar hasta guardar y eliminar datos, usando las poderosas herramientas que ofrece Spring.
¿Qué es un repositorio en Spring?
Un repositorio en Spring es una clase que se encarga de realizar operaciones sobre la base de datos. Para lograr esto, utilizamos la anotación @Repository, que indica a Spring que la clase interactúa directamente con la base de datos. Además, podemos usar @Component, que es más genérica, pero @Repository es más específica y adecuada para nuestras necesidades.
importorg.springframework.stereotype.Repository;@RepositorypublicclassProductoRepositorio{// Métodos para CRUD}
¿Cómo consultar un producto en particular?
Para consultar un producto específico, puedes utilizar el método findById del CrudRepository de Spring Data. Este método busca un registro específico con una clave primaria, en este caso un ID.
La anotación @Repository es un estereotipo de Spring, crucial para indicar que una clase maneja operaciones de persistencia. Esto facilita la organización y el mantenimiento del código, ayudando a Spring a gestionar las excepciones automáticamente y proporcionando una capa adicional para la gestión de datos.
Incorporar estas buenas prácticas y comprender la diferencia entre @Component y @Repository refuerza el código y asegura su claridad y eficacia. Con esta base, estás preparado para seguir avanzando en las otras capas de tu aplicación de manera organizada y eficaz.
Mantén tu motivación alta y sigue explorando, ¡cada nuevo concepto es un paso más hacia el dominio de Spring Framework!
@Repository: le indicamos a la clase que es la encarga de interactuar con la base de datos.
@Component: le indicamos que es un componente de spring.
El primero es mejor porque indicamos el tipo de componente que es.
👍
👏👏
Quede con una duda, si ProdcutCrudRepository se creo como una interfaz ¿Por que nunca se llego a implementar, sino que se trato como una clase?
Inyectamos ProductCrudRepository en el Repository y lo usamos directamente porque extiende de CrudRepository, que es una funcionalidad que nos brinda Spring Data para interactuar con la base de datos sin necesidad de implementar. ¡Únicamente tenemos que utilizarla! Genial, no?
Lo implementa Spring a través de la inversión de dependencia.
Es posible dejar @Repository en la interfaz?
No, esta anotación siempre debe ir en la implementación de la interfaz.
Muy buena pregunta
tengo una duda, por que no @Repository iría en ProductoCrudRepository, y esta clase que es ProductoRepository en seria un @Service si tiene prácticamente todo los parámetros que se están colocando en esta clase, sentía que estamos duplicando código
Concuerdo contigo, veo que sería mas productivo tenerlo como @Service
El repositorio (ver Repository Pattern) es una capa de abstracción que se añade a tu sistema para desacoplar el motor de base de datos de tu aplicación, básicamente te ayuda a que tu aplicación no dependa del tipo de base de datos que estas utilizando, si mañana quisieras cambiar Postgres por mysql o MongoDB, solo tendrías que modificar el repositorio y el resto de tu aplicación no debería verse afectada en gran medida (sería lo ideal). Esta capa es solo para interactuar con tu base de datos y NO posee lógica de negocio.
Un service por el contrario, es la capa que guarda la mayor parte de la lógica de tu negocio y su responsabilidad es esa, implementar lógica, no relacionarse con una base de datos.
con la anotacion @Repository indicamos que la clase interactua con la base de datos
👍
Me ha parecido genial el curso! tengo una duda
¿Me podrían ayudar a entender la diferencia entre Optional<Producto> y Producto? min 2:41
Se utiliza Optional para definir un objeto que puede (o no) tener contenido, en el caso de la función getEscasos, si todos los productos tuvieran un stock alto, la consulta no traería resultados.
En el curso de programación funcional con java explican este tema.
Una pregunta:
¿Es correcto poner la anotación @Autowired en:
private ProductoCrudRepository productoCrudRepository;?
Si, por que estamos inyectando otras dependencias en este caso **ProductoCrudRepository **
Que sucede si no usamos la anotación @Repository o @Component en el repositoy?
Sí no usamos ninguna de estás dos anotaciones lo que va a pasar es que no podremos inyectar luego el componente en el servicio porque es un bean no gestionado por la inversión de control que manejamos con Spring.
La clase ProductoRepository no deberia ir en el paquete domain.repository?
A priori pareciera que fuera así, pero algunas clases más adelante te soluciono esa duda. Esta clase no va dentro del domain porque si te fijas interactúa directamente con la base de datos, entonces está mas relacionada con la capa de persistencia.
Gracias por estar atento a las dudas.
Utilizando chatGPT consultando como aplicamos el patrón CQRS nos da la guía siguiente:
Aplicar el patrón CQRS (Command Query Responsibility Segregation) en Spring Boot, puedes seguir los siguientes pasos:
Crea dos interfaces para tu repositorio, una para las operaciones de lectura (query) y otra para las operaciones de escritura (command). Por ejemplo, puedes llamarlas ReadRepository y WriteRepository, respectivamente.
En la interfaz ReadRepository, extiendes de CrudRepository o cualquier otra interfaz de lectura que desees utilizar. En ella, colocas solo los métodos de lectura necesarios para tu aplicación, como findAll(), findById(), etc.
En la interfaz WriteRepository, extiendes de JpaRepository o cualquier otra interfaz de escritura que desees utilizar. En ella, colocas solo los métodos de escritura necesarios para tu aplicación, como save(), delete(), etc.
Crea una clase de implementación para cada interfaz, por ejemplo, ReadRepositoryImpl y WriteRepositoryImpl. Estas clases deben implementar los métodos correspondientes de cada interfaz.
Utiliza estas interfaces y clases en tus servicios para dividir las responsabilidades de lectura y escritura en diferentes capas de tu aplicación.
Con estos pasos estaras implementando el patrón CQRS en tu aplicación con Spring Boot. Sin embargo, es importante mencionar que CQRS no solo se trata de separar las operaciones de lectura y escritura en diferentes capas, sino que también implica una separación lógica en la estructura de la base de datos y en el diseño de las consultas.
Si, he visto que en la interfaz de CrudRepositiry lo usan en la capa dao, y usan un paquete de servicio donde agregan una interface donde ponen los métodos a usar y se crean clases de implementación usando esta interface, agregando la notación @service donde están los métodos que usan los querys del crud
Continuemos, todo va bien al parecer hasta este momento, excelente explicación del profesor.
x2
Una duda, ¿Por qué la clase ProductoRepository no la estamos guardando dentro de la carpeta Repositories del Domain?
Si hacemos esto solo para Producto me imagino aremos lo mismo para el resto de las entidades no hay forma de hacer algo generico que nos sirva para todas las entidades ?
¿Por que es recomendable utilizar este wrapper de Repository, y no utilizar directamente la interfaz CRUDRepository en los servicios o los controladores?
Es bueno separar los intereses de nuestras capas. No usamos CrudRepository en el Service sino más bien con la implementación de Repository porque es posible que luego queramos, por ejemplo, usar una base de datos NoSQL y en ese caso lo que debemos hacer es simplemente crear otra implementación del Repository.
Sí llamáramos directamente al CrudRepository desde el Service, tendríamos entonces que hacer un nuevo Service o hacer un refactor sí vamos a usar otra fuente de datos como la mencionada (NoSQL).
Buen día compañero y Profe Alejandro, por my parte creo que con lo que hemos visto hasta el momento no ha sido necesaria crear la implementación de nuestro repositorio, ya que los metodos que estamos escribiendo se podrian llamar directamente en la capa del servicio, por mi parte realizaría la implemmentación es caso de llamar un procedimiento almacenado de la base de datos. Y si la implementación se utilizó solo para realizar la prueba del Repositorio, sería una buena parte realizarlo en un Junit. Comparto el código que llevamos hasta el momento 👍.
https://github.com/borisbikes/platzi/tree/main/Spring/platzi-market
@Repository es la clase que se encarga de interactuar con nuestra base de datos.
desde ProductoRepository hacemos las interacciones con la base de datos.
@Component es una anotacion que generalizacion de anotaciones.
El uso de Optional en Java permite manejar valores que pueden ser nulos de manera más segura y legible. En lugar de retornar un objeto que podría ser null, un método puede retornar un Optional<T>, indicando que el valor está presente o no. Esto evita errores comunes como el NullPointerException. Se puede utilizar métodos como isPresent(), ifPresent(Consumer<? super T> action) y orElse(T other) para manejar la lógica de manera más expresiva. En el contexto de tu curso, es útil al implementar métodos en el repositorio, como el que consulta productos por ID.
Hola 👋🏼
¿Alguien ha tenido problemas para usar @Repository con la versión 3.3.5 de spring?
¿Qué diferencia hay de hacerlo así, a hacerlo creando una interfaz para los servicios e inyectándola en una clase con notación @Service vía @Autowired?
Buenos días Alejandro y compañeros de clase
Tengo una inquietud: No me queda claro cuándo usar Optional. En qué ocasiones debo usarlo?
Gracias
Hola Juan, Optional se usa cuando una informacion que requieras por ejemplo de una base de datos o de alguna api que estes consumiendo no de errores de NullPointerException cuando este no este disponible o no tenga datos para devolverte, es como una protección de parte de Java para que no se "rompa" tu aplicacion cuando no haya informacion disponible. Espero haberte ayudado! Saludos.