在 Spring Boot 应用程序中将 MapStruct 与 Lombok 结合使用的方法

在本文中,您将找到有关如何高效使用 MapStruct、Lombok 和 Spring Boot 的代码示例和说明。

介绍

        当您实现任何规模的服务时,您通常需要将数据从一种结构移动到另一种结构。通常,这是在不同逻辑层使用的相同数据 - 在业务逻辑、数据库级别或用于传输到前端应用程序的控制器级别。

        要传输这些数据,您必须重复大量样板文件。真累。我想提请您注意一个可以帮助您节省精力的图书馆。认识 MapStructure!

使用这个库,您只能指定结构映射方案。其实现将由图书馆自行收集。

在哪里可以找到它

最新版本可以在Maven 中央存储库中找到。
您可以将其添加到您的pom.xml:

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

您需要在插件中添加注释处理器:

<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>

如果您使用 Gradle,可以将其添加到您的build.gradle

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

怎么运行的

我们以一些数据类为例:

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
}

这就是我们需要为其实现编写的所有代码:

@Mapper
public interface CatMapper {

    CatEntity toEntity(CatDto dto);

    CatDto toDto(CatEntity entity);
}

该接口的实现将由 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;
    }
}

如何将 MapStruct 与 Java 记录一起使用

在Java 14中,添加了记录类。MapStruct 也可以处理它们:

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

如果我们创建一个映射接口:

@Mapper
public interface CatRecordMapper {

    CatEntity toEntity(CatRecord record);

    CatRecord toRecord(CatEntity entity);
}

然后 Mapstruct 将生成如下实现:

@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;
    }
}

如何将 MapStruct 与 Project Lombok 结合使用

        在Java世界中,有一个广为人知的大型库——Project Lombok。它还可以减少开发人员必须编写的样板代码。有关该库的更多详细信息,您可以在官方网站上找到。
要将此库添加到您的项目中,您需要将其添加到 pom.xml 中:

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

 而且,您需要将其添加到注释处理器中:

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

对于 Gradle 来说,稍微简单一些。只需将其添加到  build.gradle

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

并且迈出了重要的一步!要将 Project Lombok 与 MapStruct 集成,您需要添加绑定库:

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

对于我们的示例,使用@Data注释就足够了,它添加了 getter 和 setter。

@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;
}

对于同一个mapper接口,它会生成以下实现:

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;
    }
}

如何将 Spring Boot 逻辑添加到 Mapper 中

有时需要从Spring的bean中检索一些字段。假设我们不在数据库中存储权重信息,这在 Entity 中是无法访问的。相反,我们有一些 Spring 的服务来提供此信息。

@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;
    }
}

要使用此 bean 检索映射器接口内的权重信息,应将其替换为具有描述所有附加逻辑的方法的抽象类。

@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);
    }
}

在这种情况下,MapStruct将生成这个抽象类的实现:

@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;
    }
}

如何忽略字段并映射具有不同名称的字段

例如,数据库实体中的字段和 dto 中的字段具有不同的名称。 

例如,我们需要忽略 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;
}

可以通过以下参数来完成:

@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);
}

因此,MapStruct 的实现将是:

@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;
    }
}

结论

        我们已经介绍了开发多层应用程序时出现的最流行的场景。因此,Project Lombok 和 MapStruct 库的结合可以显着节省开发人员在样板文件上的时间和精力。
感谢您的关注!

猜你喜欢

转载自blog.csdn.net/qq_28245905/article/details/132128037