Formas de utilizar MapStruct con Lombok en una aplicación Spring Boot

En este artículo, encontrará ejemplos de código e instrucciones sobre cómo utilizar MapStruct, Lombok y Spring Boot de forma eficaz.

introducir

        Cuando implementas un servicio de cualquier tamaño, a menudo necesitas mover datos de una estructura a otra. Por lo general, se trata de los mismos datos que se utilizan en diferentes capas lógicas: en la lógica empresarial, en el nivel de la base de datos o en el nivel del controlador para transferirlos a la aplicación front-end.

        Para transferir estos datos, hay que repetir muchos textos repetitivos. realmente cansado. Me gustaría llamar su atención sobre una biblioteca que puede ayudarle a ahorrar energía. ¡Conoce MapStructure!

Con esta biblioteca, sólo puede especificar esquemas de mapeo de estructuras. Su ejecución será recogida por la propia biblioteca.

donde encontrarlo

La última versión se puede encontrar en el repositorio central de Maven.
Puedes agregar esto a tu pom.xml:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>

Debes agregar un procesador de anotaciones en el complemento:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.5.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <annotationProcessorPaths>
            <path>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>1.5.5.Final</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

Si usa Gradle, puede agregar esto a su build.gradle:

implementation "org.mapstruct:mapstruct:${mapstructVersion}"
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"

cómo funciona

Tomemos algunas clases de datos como ejemplo:

public class CatEntity {
    private Long id;
    private String name;
    private String color;
    // getters and setters
}
 
public class CatDto {
    private Long id;
    private String name;
    private String color;
    // getters and setters
}

Este es todo el código que necesitamos escribir para su implementación:

@Mapper
public interface CatMapper {

    CatEntity toEntity(CatDto dto);

    CatDto toDto(CatEntity entity);
}

Las implementaciones de esta interfaz serán creadas por el propio MapStruct:

@Generated
public class CatMapperImpl implements CatMapper {

    @Override
    public CatEntity toEntity(CatDto dto) {
        if ( dto == null ) {
            return null;
        }

        CatEntity catEntity = new CatEntity();

        catEntity.setId( dto.getId() );
        catEntity.setName( dto.getName() );
        catEntity.setColor( dto.getColor() );

        return catEntity;
    }

    @Override
    public CatDto toDto(CatEntity entity) {
        if ( entity == null ) {
            return null;
        }

        CatDto catDto = new CatDto();

        catDto.setId( entity.getId() );
        catDto.setName( entity.getName() );
        catDto.setColor( entity.getColor() );

        return catDto;
    }
}

Cómo utilizar MapStruct con registros Java

En Java 14, se agregó la clase de registro. MapStruct también puede manejarlos:

public class CatEntity {
    private Long id;
    private String name;
    private String color;
    // getters and setters
}
 
public record CatRecord(
    Long id,
    String name,
    String color
) {
}

Si creamos una interfaz de mapeo:

@Mapper
public interface CatRecordMapper {

    CatEntity toEntity(CatRecord record);

    CatRecord toRecord(CatEntity entity);
}

Luego Mapstruct generará la siguiente implementación:

@Generated
public class CatRecordMapperImpl implements CatRecordMapper {

    @Override
    public CatEntity toEntity(CatRecord record) {
        if ( record == null ) {
            return null;
        }

        CatEntity catEntity = new CatEntity();

        catEntity.setId( record.id() );
        catEntity.setName( record.name() );
        catEntity.setColor( record.color() );

        return catEntity;
    }

    @Override
    public CatRecord toRecord(CatEntity entity) {
        if ( entity == null ) {
            return null;
        }

        Long id = null;
        String name = null;
        String color = null;

        id = entity.getId();
        name = entity.getName();
        color = entity.getColor();

        CatRecord catRecord = new CatRecord( id, name, color );

        return catRecord;
    }
}

Cómo utilizar MapStruct con Project Lombok

        En el mundo Java, existe una gran biblioteca muy conocida: Project Lombok. También reduce el código repetitivo que los desarrolladores tienen que escribir. Más detalles sobre la biblioteca se pueden encontrar en el sitio web oficial.
Para agregar esta biblioteca a su proyecto, debe agregar esto a pom.xml:

<dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.28</version>
        <scope>provided</scope>
</dependency>

 Y debe agregar esto a su procesador de anotaciones:

<annotationProcessorPaths>
    <path>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.28</version>
    </path>
</annotationProcessorPaths>

Para Gradle, es un poco más fácil. solo agrégalo a  build.gradle

implementation 'org.projectlombok:lombok:1.18.28'
annotationProcessor "org.projectlombok:lombok:1.18.28"

¡Y se ha dado un paso importante! Para integrar Project Lombok con MapStruct, debe agregar la biblioteca de enlaces:

annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'

Para nuestro ejemplo, @Dataes suficiente usar anotaciones, que agregan captadores y definidores.

@Data
public class CatDto {
    private Long id;
    private String name;
    private String color;
}

@Data
public class CatEntity {
    private Long id;
    private String name;
    private String color;
}

Para la misma interfaz del mapeador, genera las siguientes implementaciones:

public interface CatMapper {
    CatEntity toEntity(CatDto dto);
    CatDto toDto(CatEntity entity);
}

@Generated
public class CatMapperImpl implements CatMapper {

    @Override
    public CatEntity toEntity(CatDto dto) {
        if ( dto == null ) {
            return null;
        }

        CatEntity catEntity = new CatEntity();

        catEntity.setId( dto.getId() );
        catEntity.setName( dto.getName() );
        catEntity.setColor( dto.getColor() );

        return catEntity;
    }

    @Override
    public CatDto toDto(CatEntity entity) {
        if ( entity == null ) {
            return null;
        }

        CatDto catDto = new CatDto();

        catDto.setId( entity.getId() );
        catDto.setName( entity.getName() );
        catDto.setColor( entity.getColor() );

        return catDto;
    }
}

Cómo agregar lógica Spring Boot a Mapper

A veces es necesario recuperar algunos campos de un Spring Bean. Suponiendo que no almacenamos información de peso en la base de datos, no se puede acceder a ella en Entity. En cambio, tenemos algunos servicios Spring para proporcionar esta información.

@Data
public class CatDto {
    private Long id;
    private String name;
    private String color;
    private Integer weight;
}


@Data
public class CatEntity {
    private Long id;
    private String name;
    private String color;
}
And there is service that provides weight information:

@Service
public class CatWeightProvider {

    public Integer getWeight(String name) {
        // some logic for retrieving weight info
        return 5;
    }
}

Para utilizar este bean para recuperar información de peso dentro de la interfaz del asignador, se debe reemplazar por una clase abstracta con métodos que describan cualquier lógica adicional.

@Mapper(componentModel = "spring")
public abstract class CatMapper {

    @Autowired
    private CatWeightProvider provider;

    @Mapping(target = "weight", source = "entity.name", qualifiedByName = "retrieveWeight")
    public abstract CatDto toDto(CatEntity entity);

    @Named("retrieveWeight")
    protected Integer retrieveWeight(String name) {
        return provider.getWeight(name);
    }
}

En este caso MapStruct generará una implementación de esta clase abstracta:

@Generated
@Component
public class CatMapperImpl extends CatMapper {

    @Override
    public CatDto toDto(CatEntity entity) {
        if ( entity == null ) {
            return null;
        }

        CatDto catDto = new CatDto();

        catDto.setWeight( retrieveWeight( entity.getName() ) );
        catDto.setId( entity.getId() );
        catDto.setName( entity.getName() );
        catDto.setColor( entity.getColor() );

        return catDto;
    }
}

Cómo ignorar campos y asignar campos con nombres diferentes

Por ejemplo, un campo en una entidad de base de datos y un campo en un dto tienen nombres diferentes. 

Por ejemplo, debemos ignorar los pesos de los campos en la capa dto.

@Data
public class CatDto {
    private String name;
    private String color;
    private Integer weight;
}

@Data
public class CatEntity {
    private Long idInDatabase;
    private String nameInDatabase;
    private String colorInDatabase;
}

Esto se puede hacer con los siguientes parámetros:

@Mapper
public interface CatMapper {

    @Mapping(target = "weight", ignore = true)
    @Mapping(target = "name", source = "entity.nameInDatabase")
    @Mapping(target = "color", source = "entity.colorInDatabase")
    CatDto toDto(CatEntity entity);
}

Por tanto, la implementación de MapStruct será:

@Generated
public class CatMapperImpl implements CatMapper {

    @Override
    public CatDto toDto(CatEntity entity) {
        if ( entity == null ) {
            return null;
        }

        CatDto catDto = new CatDto();

        catDto.setName( entity.getNameInDatabase() );
        catDto.setColor( entity.getColorInDatabase() );

        return catDto;
    }
}

en conclusión

        Hemos cubierto los escenarios más populares que surgen al desarrollar aplicaciones de varios niveles. Por lo tanto, la combinación de Project Lombok y la biblioteca MapStruct puede ahorrar significativamente a los desarrolladores tiempo y esfuerzo en texto estándar.
¡Gracias por su atención!

Supongo que te gusta

Origin blog.csdn.net/qq_28245905/article/details/132128037
Recomendado
Clasificación