Mapeadores en Java para Conversión de Compras y Productos
Resumen
¿Cómo configurar un mapeador de elementos de compra en una API?
Explorar las técnicas y herramientas necesarias para trabajar con mapeadores en tu API puede parecer desafiante al principio, pero con un enfoque sistemático, este proceso puede simplificarse. En el caso de los mapeadores para elementos de compra, primero es crucial configurar un mapeador de elementos de compra eficiente, el cual te permitirá convertir entidades de compra de productos a objetos de tipo purchase item dentro de tu aplicación. Vamos a sumergirnos en el detalle del código para lograr estos objetivos.
¿Cómo configuro un mapeador para la entidad de compra completa?
El siguiente paso en nuestro viaje de mapeo implica la creación de un mapeador para la entidad de compra completa. Aquí aplicaremos conceptos similares para convertir una compra a un objeto de tipo purchase.
¿Qué beneficios ofrecen los mapeadores en sistemas de compras?
Los mapeadores maximizan la eficiencia en el manejo de conversiones entre entidades complejas en una API. Al implementar mapeadores:
Uniformidad y claridad: Se establece un estándar para conversiones que garantiza consistencia en el manejo de datos.
Mantenimiento simplificado: Facilitan el mantenimiento al centralizar las configuraciones de mapeo en un único lugar.
Inyección de dependencias: Mediante la anotación @Mapper, se habilita la inyección de estas interfaces donde sea necesario, optimizando el flujo de trabajo.
¿Cómo configuro adecuadamente las anotaciones y métodos?
Las anotaciones son esenciales para definir correctamente los flujos de conversión. Utilizando @Mappings y @Mapping, es posible especificar claramente qué atributos se transfieren o ignoran durante la conversión. También es crucial entender el uso de @InheritInverseConfiguration para invertir configuraciones previamente definidas, lo que potencia la reutilización de código y evita redundancias.
Consejos para una implementación exitosa
Comprende el esquema de tus datos: Antes de implementar los mapeadores, asegúrate de entender cómo están estructuradas tus entidades y sus relaciones.
Verifica los nombres de atributos: Los errores comunes en el mapeo suelen derivarse de líos con los nombres de los atributos. Revisa minuciosamente cuál es el nombre correcto de cada atributo en tus fuentes y destinos.
Pruebas exhaustivas: Aunque los mapeadores estén configurados, es esencial validar su funcionalidad mediante pruebas para asegurar la integración correcta de los datos.
Avanzar en el robusto campo de la gestión de compras requiere habilidades con herramientas modernas para mapeo de datos. Con esta guía y ejemplos de código, te estarás posicionando para asegurar una integración eficaz y fluida en tus aplicaciones. ¡Ánimo y adelante!
y no afecta su funcionamiento de las dos maneras funciona.
Muy bien.
👍
Les quiero comentar que tuve un problema con la actualización de lo siguiente:
@Mapping(source = "productos", target = "items" ),
(al autocompletar luego de cambiar item por items INTELLIJ no actualizaba el auto completar con ITEMS tuve que volver a la clase Purchase.java y quitar el método y volver a generar el getter an setter algo paso con el INTELLIJ. Por si a alguien mas le pasa para que pueda saber como solucionarlo. :)
A mí me pasó lo mismo y lo "solucioné" igual que tú. También me pasó que el autocompletar, para @Mapping(source="id.idProducto", ...), no me detectaba el autocompletado de idProducto y hasta ahora no lo he solucionado, ¿encontraste alguna solución general para tu caso?
Entendido
Para los que vienen siguiendo paso a paso el ejemplo, en los campos de ComprasProducto que tienen relaciones, no habiamos creado los getters y setters. Me di cuenta porque no me autocompletaba MapStruct dentro de target
👍
Yo tuve un problema con esto; cuando cree los getters y setters para el atributo "compra" dentro de ComprasProducto, el setter lanzaba un error sobre this.compra: "Cannot access com.platzi.platzimarket.persistence.entity.Compra". Si elimino el setter, la app corre, pero siento que es porque en el PurchaseItemMapper se está ignorando compra en el reverse mapping (ver video en 5:32) . De remate, nunca me autocompletó nada el MapStruct... alguien tiene idea de que está pasando?
Yo uso Lombok para evitar escribir los getter and setter, esto es una buena practica?
Creo que no por que es una dependencia obsoleta
Desde que no interfiera (no lo hace) con el proyecto, lo puedes usar con confianza
En la clase destino siempre deben hacerse todos los mappings, si no se tienen todos los atributos mapeados, se tienen que ignorar explícitamente
Sí bien lo explico así porque me gusta tener control visual de todos los atributos a la hora de mapearlos, también podrías agregar el parámetro unmappedTargetPolicy = ReportingPolicy.IGNORE en la anotación @Mapper para no tener que ignorarlos explícitamente en los métodos con ignore = true. Por ejemplo, para el PurchaseMapper sería algo así:
incluso recomiendo agregar el parametro "unmappedTargetPolicy = ReportingPolicy.ERROR", que hace saltar un error en tiempo de compilación en caso de que te haya faltado mapear alguna relación o ignore específico. Ayuda mucho para evitar dolores de cabeza después cuando alguna consulta no se comporta como esperamos
El agregar una lista en un Optional se considera un Code Smell, debido a que si no hay datos nos regresa una lista vacía.
es verdad, pero podes hacer algo como esto para asegurarte de que el optional se devuelva vacio si contiene un listado sin elementos:
publicOptional<List<ProductDto>>getByCategory(long categoryId){return productRepo.getByCategory(categoryId).filter(prods ->!prods.isEmpty());}```llamando al metodo .filter del opcional, podes filtrar el contenido para incluirlo solo si tiene elementos.el optional retornado entonces es el mismo si existen elementos dentro de la lista, o un optional vacio en caso de haber contenido una lista vacia.
En la mayoría de los casos, devolver una lista vacía es suficiente y más claro que usar un Optional<List<T>>. Si encuentras que estás usando Optional para listas o colecciones, deberías reconsiderar si realmente es necesario o si devolver una colección vacía es más apropiado. El uso de Optional está más alineado con representar la ausencia de un valor único, no la ausencia de elementos en una colección.
Si tiene un error que dice
Unknown property "compra" in result type ComprasProducto. Did you mean "total"?
Es porque en la clase ComprasProductos.java tienen que agregar los setters and getters que faltan
Joven excelente aporte!
Alguien sabe como solucionar este error de la consola de Spring cuando se hace la petición Http desde Postman?
he visto que hay como pagina las listas ya que si trabajamos con 10 o 100 elementos es rapido en frontend pero si hablamos 1000 ya comienza a hacerse lento como puedo hacer esto com mapping
Spring Data soporta los paginadores al momento de crear nuestros Query Methods. Asimismo, sí el dto tambien tiene paginador, MapStruct haría esta conversión automáticamente.
Puedes probar y me dices que tal te va.
buenas noches me gustaria preguntar si alguen le ha marcado este error:
Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.sql.ast.tree.from.UnknownTableReferenceException: Unable to determine TableReference (productos) for com.platzi.market.persistence.entity.Compra.productos.{fk-target}
¡Hola!
¿Los atributos que tienen el @JoinColumn deberían también tener los getters y los setters o hay algo en las buenas prácticas que indique que no es necesario?