程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(3)

MapStruct快速上手

发布于2020-11-19 20:21     阅读(911)     评论(0)     点赞(16)     收藏(1)


概述

随着软件架构分层的出现和发展,那么各个层次之间的数据模型的相互转换问题凸显,如PO、DO、DTO、VO等。

之前做法


    public UserVo convertDO(UserDo userDo){
    	if(null == userDo){
			return null;
		}
        UserVo vo = new UserVo();
        vo.setUserId(userDo.getUserId());
        vo.setUsername(userDo.getUsername());
        vo.setAddtime(userDo.getAddtime());
        
        return vo;
    }

冗长耗时,
MapStruct应运而生,目标就是通过自动化的方式简化这项工作。

Maven依赖

...
<properties>
    <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source> <!-- depending on your project -->
                <target>1.8</target> <!-- depending on your project -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                    <!-- other annotation processors -->
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

实战演练

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Car {

    private String make;
    private int numberOfSeats;
    private CarType type;

}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CarDto {
    private String make;
    private int seatCount;
    private String type;
}

public enum CarType {
    SEDAN;
}

@Mapper
public interface CarMapper {
    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );

    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
}

测试

@SpringBootTest
class CarMapperTest {

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

要点攻略

  • 默认转换规则
  1. 名称相同的字段(如:id,id)
  2. 名称相同类型不同且可转换的字段(如:String Integer)
  3. 指定了前后名称差异的字段(如:source = “numberOfSeats”, target = “seatCount”)

名称对应,但类型不可转换的属性。转换时,不抛异常,target属性默认为null

  • 自动映射的类型

Java基本类型和他们的包装类型(包装类null转基本类型默认不抛异常、填充基本类型的默认值0或false)

Java数值类的基本类型和他们的包装类型(如:int/long/byte,数值和精度可能有损)

Java基本类型、他们的包装类型和String

    @Mapping(source = "price", numberFormat = "$#.00")
    CarDto carToCarDto(Car car);

    @IterableMapping(numberFormat = "$#.00")
    List<String> prices(List<Integer> prices);

枚举类和String

Date和String

    @Mapping(source = "manufacturingDate", dateFormat = "dd.MM.yyyy")
    CarDto carToCarDto(Car car);

    @IterableMapping(dateFormat = "dd.MM.yyyy")
    List<String> stringListToDateList(List<Date> dates);

DateTime LocalDateTime LocalDate LocalTime 和String

等等,这里不再一一列举

  • 名字不一致
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
    
    @Mapping(source = "person.description", target = "description")
    @Mapping(source = "hn", target = "houseNumber")
    DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Integer hn);

  • 表达式
@Mapper
public interface SourceTargetMapper {

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

    @Mapping(target = "timeAndFormat",
         expression = "java( new org.sample.TimeAndFormat( s.getTime(), s.getFormat() ) )")
    Target sourceToTarget(Source s);
}

或者主动导入

imports org.sample.TimeAndFormat;

@Mapper( imports = TimeAndFormat.class )
public interface SourceTargetMapper {

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

    @Mapping(target = "timeAndFormat",
         expression = "java( new TimeAndFormat( s.getTime(), s.getFormat() ) )")
    Target sourceToTarget(Source s);
}

  • 忽略部分字段
    @Mapping(target = "fish.name", ignore = true)
    FishTankDto map( FishTank source );
  • 类型不一致
// 自定义转换方法 通过表达式实现不同类型的转换
    @Mapping(target = "address",expression = "java(homeAddressToString(dto2do.getAddress()))")
    PersonDO dto2do(PersonDTO dto2do);

    default String homeAddressToString(HomeAddress address){

        return JSON.toJSONString(address);

    }

  • 自定义常量
    @Mapping(target = "stringProperty", source = "stringProp", defaultValue = "undefined")
    @Mapping(target = "longProperty", source = "longProp", defaultValue = "-1")
    @Mapping(target = "stringConstant", constant = "Constant Value")
    @Mapping(target = "integerConstant", constant = "14")
    @Mapping(target = "longWrapperConstant", constant = "3001")
    @Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014")
    @Mapping(target = "stringListConstants", constant = "jack-jill-tom")
    Target sourceToTarget(Source s);
  • 多数据源
    @Mapping(source = "person.description", target = "description")
    @Mapping(source = "address.houseNo", target = "houseNumber")
    DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Address address);
}

  • 集合转换
    Set<String> integerSetToStringSet(Set<Integer> integers);

    List<CarDto> carsToCarDtos(List<Car> cars);

    CarDto carToCarDto(Car car);

想了解更多内容,请查看官网↓

Reference

  • https://mapstruct.org/
  • https://github.com/mapstruct/mapstruct
  • https://mapstruct.org/documentation/stable/reference/html/
  • https://mp.weixin.qq.com/s/z7esaXjX8fuYBnkZ41TLTg


所属网站分类: 技术文章 > 博客

作者:javagogogo

链接:http://www.javaheidong.com/blog/article/911/77546a10e48256c30518/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

16 0
收藏该文
已收藏

评论内容:(最多支持255个字符)