¿Cómo crear un paquete y una interfaz para los mapeadores?
Al trabajar en desarrollos de software, es esencial contar con herramientas que faciliten la transformación de datos entre diferentes capas del sistema. Una de esas herramientas es MapStruct, que nos permitirá generar mapeadores para traducir objetos de dominio a entidades y viceversa. Para comenzar, debemos:
Crear un nuevo paquete en nuestro proyecto, al cual llamaremos Mapper.
Dentro de este paquete, necesitamos crear interfases específicas para cada mapeador: CategoryMapper y ProductMapper.
Esto se hace seleccionando "new package" y posteriormente "new interfaz" en nuestro IDE. Estos mapeadores serán fundamentales para asegurar que las conversiones se realicen de manera eficiente y precisa.
¿Qué anotaciones se deben utilizar en un mapeador?
MapStruct nos ofrece una sintaxis clara y precisa para definir nuestras conversiones:
@Mapper: Esta anotación debe añadirse a cada interfaz para indicar que se trata de un mapeador MapStruct.
componentModel = "spring": Se establece como parte de @Mapper, permitiendo integrar MapStruct con Spring. Indica que nuestro mapeador debe comportarse como un componente Spring.
Definir estas anotaciones garantiza que MapStruct gestione correctamente la creación de instancias de mapeadores y su integración con el ciclo de vida de Spring.
¿Cómo definir métodos de conversión?
Los métodos de conversión transforman un tipo de objeto en otro. Aquí definimos métodos para convertir Category y Product en sus equivalentes del dominio.
Aquí, @Mapping configura cómo se mapean fielmente los datos desde idCategoria, descripcion, y estado hacia sus respectivos atributos en la entidad Category.
Conversión inversa y manejo de atributos ignorados
Para realizar mapeos inversos (de Category a Categoria) y asegurarse de ignorar ciertos atributos que no son necesarios en el lado de la entidad, MapStruct permite el uso de:
@InheritInverseConfiguration: Facilita que la conversión inversa utilice las mismas reglas ya definidas.
Para ignorar campos específicos, utilizamos:
@Mapping(target ="productos", ignore =true)
Implementar estas configuraciones limita el código redundante y simplifica el manejo de atributos compatibles entre sistemas.
¿Cómo usar mapeadores para productos?
La interfaz ProductMapper sigue un diseño similar:
Aquí, aseguramos la transformación precisa de cada atributo, utilizando CategoryMapper para manejar las conversiones involucradas con el atributo categoria.
Manejo de listas y conversión inversa
La interfaz también debería incluir métodos para manejar listas de productos y realizar la conversión inversa:
Estos métodos optimizan la gestión de múltiples productos y aseguran que todos los casos de uso de conversión están cubiertos de manera eficiente.
¿Qué beneficios ofrece MapStruct en el desarrollo?
MapStruct simplifica la configuración de mapeadores, lo que reduce el tiempo de desarrollo e incrementa la legibilidad, mantenibilidad y precisión de las conversiones de datos. Incentiva a los desarrolladores a estructurar su código de manera modular y reutilizable.
Reflexionar sobre cómo estos mapeadores integran diferentes capas en tu aplicación te abrirá a implementar soluciones más efectivas y robustas en futuros proyectos. Continúa explorando y dominando herramientas como MapStruct para maximizar la eficiencia de tu desarrollo.
No hice caso al viajero del tiempo de no tratar de implementar la Aplicación en Inglés desde el principio :)
A rehacer, mejor más aprendemos!
Jajaja me paso lo mismo, por eso me regrese a la clase donde empezaba a implementar en español y puse el mensaje para que no cometieron el error los demás.
P.D. Soy el viajero del tiempo jaja...
No es necesario rehacer todo y escribirlo en español, basta que las clase Category que creaste en el package Domain nombrarla DomainCategory y se resuelve el problema de import.
Esto del mapper, si me revento la cebeza
x2
x3
Excelente! Me impresiona la manera en la que mapstruct simplifica el código.
La verdad es muy buena la explicacion del profesor
En java antes de saber que existe mapStruct usaba ModelMapper,
el uso es mas simple en modelMapper si se trata de convertir clases con atributos con el mismo nombre por ejemplo de Categoria a CategoriaDto con los mismos atributos, veo que con mapStruct la configuracion es mucho más simple para indicar por ejemplo en este caso atributo con atributo de diferente nombre.
Cuando se mapea un atributo que es de una clase que tiene su mapper propio, dentro de la anotación @Mapper, se añade algo como lo siguiente: @Mapper(componentModel = "spring", uses = {CategoryMapper.class})
Muy buen aporte! Ejemplos muy útiles para aprovechar mapstruct.
para ignorar un atributo se escribe el siguiente codigo , se ignora los campos que se relacciona con otras tablas o campos que no necesitemos, siempre se debe ignorar si no se agrega en los campos Mappings
@Mapping(target = "nombreCampo", ignore = true)
Muchas gracias
Tengo entendido que a la hora de crear Interfaces es buena practica anteponer una i mayúscula, para denotar que se trata de una interfaz y no una clase.
Algo así
Interface: ICategoryMapper -> fijense en la (i) que viene primero.
No sabria si estoy 100% en lo correcto pero el detalle del i se usa cuando es una interfaz de comportamiento de objeto, en cambio, cuando son interfaces de estructura los nombras con el proposito de este solamente
Para los que tengan problemas con el @Data de lombok, nn vez de usar @Data se deben usar @Getter y @Setter, así el lombok no genera problemas.
Adicional colocar annotationProcessor:
A la hora de compilar el proyecto o ejecutarlo me da un error la línea
@Mapping(target ="productos", ignore =true)
de que en mi clase Categoria no existe el atributo "productos":
error:Unknown property "productos"in result type com.platzimarket.persistence.entity.Categoria.Did you mean "estado"? @Mapping(target ="productos", ignore =true)^
En mi clase Categoria si existe el atributo productos, como una List (al igual que al código que muestras y proporcionas). ¿Es un error importante o no debo tenerlo en cuenta ahora mismo? Comentando la línea me corre perfecto el proyecto hasta ahora
¡Muchas gracias de antemano! 😀
Verifica si tienes todos los setters y getters, yo también tenia ese error.
El mapeo se realiza gracias a los getters y setters de la clase. El atributo productos tiene los métodos get y set? Estoy casi seguro que es eso.
Tip: Cuando usas una versión de java posterior a la 8 puedes evitar el agrupamiento de anotaciones y simplemente puedes declararlas tal cual una después de otra.
por ejemplo:
Fuente: SonarLint
Si las variables se llaman igual, no es necesario hacer el @Mapping. La utilidad sería entonces por ejemplo no mapear algunas variables (en este caso el código de barras, por ejemplo).
A veces algunas columnas se llaman igual y otras no, por ejemplo "email" a veces lo llaman igual en bases de datos en español, entonces no sería necesario hacer el mapping de esta.
Buenas no me carga el vídeo 22, pase al vídeo 23 y funciona perfecto
Cambia el servidor en el engrane dentro del área del video.
Alejandro que tal, primero quiero felicitarte por la calidad de tus cursos, me han servido enormemente. Tengo un error cuando quiero cargar la aplicacion, me lo arroja en la linea de la interfaz ProductMapper donde va el @Mapping(source = "categoria", target = "category"), y por consola me dice que no existe una propiedad llamada categoria en el result type Producto. Pense que para esto se utilizaba el uses={CategoryMapper.class}. Agradezco tu ayuda!
Amigo, siempre que hagas una pregunta, trata de dar el mayor contexto posible, como por ejemplo adjuntando fotos de tu código y del error, así nos será mas fácil ayudarte a cualquier otra persona, si me das mas contexto con gusto intentare ayudarte a resolver tu Problema!
Hola Juan Pablo, muchas gracias!
Ya pusiste el get y set de Categoria dentro de la clase Producto? Quizás sea eso.