admin 管理员组

文章数量: 887021

Converter

业务代码中经常会用到很多实体类的值之间的相互转换,手动使用getter和setter方法进行设置值非常繁琐。会产生大量的冗余代码,且写法并不优雅。mapstract包中提供了一种快速转换实体类字段的方法。

依赖

        <dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-jdk8</artifactId><version>1.4.2.Final</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.4.2.Final</version></dependency>

基本使用

@Mapper(componentModel = "spring")
public interface DtoToBoConverter{ValidationBo DtoToBo(ValidationDto validationDto);ValidationDto BoBackDto(ValidationBo validationBo);
}

定义一个接口,使用 mapstract的 @mapper注解指定spring在编译阶段为该接口自行创建实现类,打开target文件下的对应目录可以看到生成的实现类如下

@Component
public class DtoToBoConverterImpl implements DtoToBoConverter {@Overridepublic ValidationBo DtoToBo(ValidationDto validationDto) {if ( validationDto == null ) {return null;}ValidationBo validationBo = new ValidationBo();validationBo.setName( validationDto.getName() );validationBo.setPrice( validationDto.getPrice() );return validationBo;}@Overridepublic ValidationDto BoBackDto(ValidationBo validationBo) {if ( validationBo == null ) {return null;}ValidationDtoBuilder validationDto = ValidationDto.builder();validationDto.name( validationBo.getName() );validationDto.price( validationBo.getPrice() );return validationDto.build();}

可以看到,生成的实现类将两个实体中同名的字段调用了getter和setter方法进行了赋值。(必须要保证字段存在对应的getter和setter方法/字段属性为public,否则将无法获取到字段)

自定义映射

想要映射的两个字段字段名不一致,可以在方法上使用@mapper注解指定不同名的字段映射

@Mapper(componentModel = "spring")
public interface DtoToBoConverter{@Mappings({@Mapping(source = "size",target = "type")})ValidationBo DtoToBo(ValidationDto validationDto);ValidationDto BoBackDto(ValidationBo validationBo);
}
validationBo.setType(validationDto.getSize());
validationBo.setName(validationDto.getName());
validationBo.setPrice(validationDto.getPrice());

List转换

  • 入参和出参中有一个是list而另一个不是 ,会提示 : Can't generate mapping method from iterable type to non-iterable type. 二至必须同时拥有或者同时没有迭代器
  • 入参和出参都为list,如果没有定义对应的实体类映射的方法,会自行创建,但是list方法上注解的@mapper将不会生效
    @Mappings({@Mapping(source = "size",target = "type")})List<ValidationBo> DtoToBo(List<ValidationDto> validationDto);
    @Overridepublic List<ValidationBo> DtoToBo(List<ValidationDto> validationDto) {if ( validationDto == null ) {return null;}List<ValidationBo> list = new ArrayList<ValidationBo>( validationDto.size() );for ( ValidationDto validationDto1 : validationDto ) {list.add( validationDtoToValidationBo( validationDto1 ) );}return list;}protected ValidationBo validationDtoToValidationBo(ValidationDto validationDto) {if ( validationDto == null ) {return null;}ValidationBo validationBo = new ValidationBo();validationBo.setName( validationDto.getName() );validationBo.setPrice( validationDto.getPrice() );return validationBo;}

常用属性

  • nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS 对参数进行非空判断
  • nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT 原参数为空,返回空对象(默认返回空)
  • 时间类型可以自动格式化,用在@mapping注解中

拷贝

mapstract由于直接调用的属性的getter和setter方法,因此转换前后的对象的对象属性其实对应的是同一块内存地址,属于浅拷贝

网上常说的mapstract是深拷贝,是使用mapstract生成一个对象的复制,这个复制和之前的对象指向两块内训地址,因此属于深拷贝。

 

本文标签: Converter