MapStruct使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MapStruct使用相关的知识,希望对你有一定的参考价值。

参考技术A 在一个成熟可维护的工程中,细分模块后,domian工程最好不要被其他工程依赖,但是实体类一般存于domain之中,这样其他工程想获取实体类数据时就需要在各自工程写model,自定义model可以根据自身业务需要而并不需要映射整个实体属性。
mapstruct这个插件就是用来处理domin实体类与model类的属性映射,定义mapper接口,mapstruct就会自动的帮我们实现这个映射接口,避免了麻烦复杂的映射实现。

开发中如需要对象转换操作可直接新建interface并继承BasicObjectMapper<SOURCE,TARGET>,并在新建的接口上加上 @Mapper(componentModel = "spring"),

文章参考:

https://blog.csdn.net/jtf8525140/article/details/78130601

https://www.tuicool.com/articles/uiIRjai

优雅的转换Bean对象 mapstruct使用笔记详解

------------恢复内容开始------------
日常开发中,我们时长会写很多关于PO转VO的代码或者是VO转DTO相关的代码,造成我们的程序异常的臃肿。

MapStruct很优雅的帮我们解决了这个问题

一、MapStruct

官网: https://mapstruct.org/

它是什么?
MapStruct 是一个代码生成器,它基于约定优于配置的方法,极大地简化了 Java bean 类型之间的映射实现。
生成的映射代码使用普通的方法调用,因此速度快、类型安全且易于理解。

为什么要用MapStruct

多层应用程序通常需要在不同的对象模型(例如实体和 DTO)之间进行映射。编写这样的映射代码是一项乏味且容易出错的任务。MapStruct 旨在通过尽可能地自动化来简化这项工作。
与其他映射框架相比,MapStruct 在编译时生成 bean 映射,这确保了高性能,允许快速的开发人员反馈和彻底的错误检查。

例如:

假设我们有一个代表汽车的类(例如一个JPA 实体)和一个伴随的数据传输对象(DTO)。

这两种类型非常相似,只是座位计数属性有不同的名称,并且 type 属性是类中的特殊枚举类型,Car但在 DTO 中是纯字符串。

二、使用mapStruct

要求jdk版本是java8或者更高

Car

public class Car 
 
    private String make;
    private int numberOfSeats;
    private CarType type;
 
    //constructor, getters, setters etc.

CarDto

public class CarDto 
 
    private String make;
    private int seatCount;
    private String type;
 
    //constructor, getters, setters etc.

要生成映射器以从对象中创建CarDto对象Car,需要定义映射器接口:
CarMapper

@Mapper 
public interface CarMapper 
 
    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); 
 
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car); 

使用映射器
基于映射器接口,客户端可以以非常简单且类型安全的方式执行对象映射:

@Test
public void shouldMapCarToDto() 
    //given
    Car car = new Car( "Morris", 5, CarType.SEDAN );
 
    //when
    CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
 
    //then
    assertThat( carDto ).isNotNull();
    assertThat( carDto.getMake() ).isEqualTo( "Morris" );
    assertThat( carDto.getSeatCount() ).isEqualTo( 5 );
    assertThat( carDto.getType() ).isEqualTo( "SEDAN" );

要求jdk版本是java8或者更高

<properties>
    <mapstruct.version>1.3.1.Final</mapstruct.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>$mapstruct.version</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-jdk8</artifactId>
        <version>$mapstruct.version</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>$mapstruct.version</version>
    </dependency>
</dependencies>

可以看到生成的源码:

public class CarMapperImpl implements CarMapper 

    @Override
    public CarDto carToCarDto(Car car) 
        if ( car == null ) 
            return null;
        

        CarDto carDto = new CarDto();

        carDto.setSeatCount( car.getNumberOfSeats() );
        carDto.setMake( car.getMake() );
        if ( car.getType() != null ) 
            carDto.setType( car.getType().name() );
        

        return carDto;
    

三、 常见用法

(1)两个类型属性不一致

此时CarPo的一个属性为carName,而CarVo对应的属性为name!

我们在接口上增加对应关系即可,如下所示


@Mapper( unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CarMapper 


    CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);

    @Mappings(
            @org.mapstruct.Mapping(source = "numberOfSeats", target = "seatCount"))
    CarDto carToCarDto(Car car);
    



(2)集合类型转换
从List转换为Lis
CarMapper

@Mapper( unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CarMapper 
    CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
    @Mappings(
            @org.mapstruct.Mapping(source = "numberOfSeats", target = "seatCount"))
    CarDto carToCarDto(Car car);
    List<CarDto> covertTo(List<Car> videoStreams);

CarMapperImpl


@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2022-01-16T21:51:16+0800",
    comments = "version: 1.4.2.Final, compiler: IncrementalProcessingEnvironment from gradle-language-java-6.8.jar, environment: Java 11.0.13 (JetBrains s.r.o.)"
)
public class CarMapperImpl implements CarMapper 

    @Override
    public CarDto carToCarDto(Car car) 
        if ( car == null ) 
            return null;
        

        CarDto carDto = new CarDto();

        carDto.setSeatCount( car.getNumberOfSeats() );
        carDto.setMake( car.getMake() );
        if ( car.getType() != null ) 
            carDto.setType( car.getType().name() );
        

        return carDto;
    

    @Override
    public List<CarDto> covertTo(List<Car> car) 
        if ( car == null ) 
            return null;
        

        List<CarDto> list = new ArrayList<CarDto>( car.size() );
        for ( Car car1 : car ) 
            list.add( carToCarDto( car1 ) );
        

        return list;
    


类型不一致

------------恢复内容结束------------

以上是关于MapStruct使用的主要内容,如果未能解决你的问题,请参考以下文章

MapStruct类型之间映射的实现

MapStruct类型之间映射的实现

MapStruct类型之间映射的实现

MapStruct - 找不到实现

MapStruct,对象装载结构工具

Mapstruct使用笔记