mapstruct 详解及使用教程

mapstruct 详解及使用教程参考链接:mapstruct的基本使用介绍是不是有时候发现明明source和target不是同一个类型,但是却转换成功了,这是因为mapstruct有一套自己的类型转换机制类型转换的流程首先尝试自动进行类型转换若是无法支持的类型转换,则是尝试调用已经存在的类型转换方法不存在可用的方法则是尝试自己创建一个类型转换方法类型转换分类自动转换以下的类型之间是mapstruct自动进行类型转换的。基本类型及其他们对应的包装类型。此时mapstruct会自动进行拆装箱。不需要人为的处理基本类型

大家好,欢迎来到IT知识分享网。mapstruct

参考链接:mapstruct的基本使用

介绍

是不是有时候发现明明source和target不是同一个类型,但是却转换成功了,这是因为mapstruct有一套自己的类型转换机制

类型转换的流程

首先尝试自动进行类型转换
若是无法支持的类型转换,则是尝试调用已经存在的类型转换方法
不存在可用的方法则是尝试自己创建一个类型转换方法

类型转换分类

自动转换

以下的类型之间是mapstruct自动进行类型转换的。

  • 基本类型及其他们对应的包装类型。
    此时mapstruct会自动进行拆装箱。不需要人为的处理
  • 基本类型的包装类型和string类型之间
@Data
@NoArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
public class Item1 { 
   
    Long itemId;
    String title;
}

@Data
@NoArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
public class Item2 { 
   
    Long itemId;
    String title;
}

@Data
@NoArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
public class Sku2 { 
   
    Long skuId;
    String skuCode;
    String skuPrice;
    List<String> nameList;
    Item1 item;
}

@Data
@NoArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
public class SkuDTO2 { 
   
    Long skuId;
    String skuCode;
    Long skuPrice;
    List<String> nameList;
    Item2 item;
}

@Mapper
public interface ItemConvert { 
   

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

    SkuDTO2 domain2Dto(Sku2 sku2);
}

// 以下为mapstruct自动生成
public class ItemConvertImpl implements ItemConvert { 
   

    @Override
    public SkuDTO2 domain2Dto(Sku2 sku2) { 
   
        if ( sku2 == null ) { 
   
            return null;
        }

        SkuDTO2 skuDTO2 = new SkuDTO2();

        skuDTO2.setSkuId( sku2.getSkuId() );
        skuDTO2.setSkuCode( sku2.getSkuCode() );
        if ( sku2.getSkuPrice() != null ) { 
   
            skuDTO2.setSkuPrice( Long.parseLong( sku2.getSkuPrice() ) );
        }
        List<String> list = sku2.getNameList();
        if ( list != null ) { 
   
            skuDTO2.setNameList( new ArrayList<String>( list ) );
        }
        skuDTO2.setItem( item1ToItem2( sku2.getItem() ) );

        return skuDTO2;
    }
    
   protected Item2 item1ToItem2(Item1 item1) { 
   
    if ( item1 == null ) { 
   
        return null;
    }

    Item2 item2 = new Item2();

    item2.setItemId( item1.getItemId() );
    item2.setTitle( item1.getTitle() );

    return item2;
}

自定义转换类型

  • 使用表达式进行定义类型转换,expression=“java(。。。)”
    注意:使用表达式的时候,类必须是全路径的使用,或者@Mapper(imports={类名.class}
@Mapper(imports={ 
   DemandSourceEnum.class})
public interface CarDealMapper { 
   
 
 CarDealMapper INSTANCE = Mappers.getMapper(CarDealMapper.class);
 
    @Mappings({ 
   
            @Mapping(target = "demandSource", expression = "java(DemandSourceEnum.getMeaning(carDealDO.getDemandSource()))"),
    SaleDemandVO doToVo(CarDealDO carDealDO);
}

  • 自定义方法进行类型转换
@Mapper
public interface ItemConvert { 
   

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

    SkuDTO2 domain2Dto(Sku2 sku2);

    default Item2 item1ToItem2(Item1 item1) { 
   
        if (item1 == null) { 
   
            return null;
        }

        Item2 item2 = new Item2();

        item2.setItemId(11111L);
        item2.setTitle(item1.getTitle());

        return item2;
    }
}

// mapstruct 的实现类
@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2019-07-30T18:38:11+0800",
    comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_101 (Oracle Corporation)"
)
public class ItemConvertImpl implements ItemConvert { 
   

    @Override
    public SkuDTO2 domain2Dto(Sku2 sku2) { 
   
        if ( sku2 == null ) { 
   
            return null;
        }

        SkuDTO2 skuDTO2 = new SkuDTO2();

        skuDTO2.setSkuId( sku2.getSkuId() );
        skuDTO2.setSkuCode( sku2.getSkuCode() );
        if ( sku2.getSkuPrice() != null ) { 
   
            skuDTO2.setSkuPrice( Long.parseLong( sku2.getSkuPrice() ) );
        }
        List<String> list = sku2.getNameList();
        if ( list != null ) { 
   
            skuDTO2.setNameList( new ArrayList<String>( list ) );
        }
        // mapstruct直接调用的是在接口中自定义的实现
        skuDTO2.setItem( item1ToItem2( sku2.getItem() ) );

        return skuDTO2;
    }
}

  • 使用策略的方式进行类型转换
    若是类型在很多Mapper中都需要使用,比较使用下例
public class BooleanStrategy { 
   

    public String booleanToString(Boolean value) { 
   

        if (value == null) { 
   
            return "--";
        }

        return value ? "是" : "否";
    }

    public Integer booleanToInteger(Boolean value) { 
   
        if (value == null) { 
   
            return null;
        }

        return value ? 1 : 0;
    }

    public Boolean IntegerToBoolean(Integer value) { 
   
        if (value == null) { 
   
            return null;
        }

        return value == 0 ? false : true;
    }

    public String dateFormate(Date date) { 
   

        if (date == null) { 
   
            return "--";
        }

        return DateFormatUtils.format(date, "yyyy-MM-dd HH:mm:ss");
    }
}


@Mapper(uses = BooleanStrategy.class)
public interface CarDealMapper { 
   
 CarDealMapper INSTANCE = Mappers.getMapper(CarDealMapper.class);
 
 CarDealDO dtoToDo(PlateCityMessageDTO plateCityMessageDTO);
}

方法中target和source 类型满足 BooleanStrategy方法的,会自动进行调用这个方法的类型转换进行处理

  • 自定义常量的方法
    若是我们需要给一些属性定义一个固定的值,这个时候可以使用 constant
    @Mapping(target = "whetherPass", constant = "true")
    CentralizedNewCarShipDTO doToDubboDto(CarDealDO carDealDO);

  • 特殊类型的转换
  @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss", expression = "java(new Date())")
    CarDTO doToDTO(CarDO carDO);

另外还有numberFormat定义数字的格式转换

  • 自定义初始值 defaultValue
    当source值为空的时候则会使用defaultValue定义的值。而constant则是无论source是否为空,都会使用constant定义的值,注意区分两者
   /** * 单个参数的直接使用 * * @param carDO source do * @return target dto */
    @Mapping(target = "userName", constant = "yby")
    @Mapping(target = "modelColor", source = "modelColor", defaultValue = "标致")
    @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss", expression = "java(new Date())")
    CarDTO doToDTO(CarDO carDO);

额外的请参考 org.mapstruct.Mapping

Collection转换

原理是遍历source collection然后转换类型,put到target collection中 如果是可以自动转换的则自动转换,同date type conversion;若是无法自动转换的,则会查看是否有可以调用的类型

@Mapper(imports = Date.class)
public interface CarMapper { 
   

    CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
    
     /** * 基本类型collection的转换 * * @param integers * @return */
    Set<String> integerSetToStringSet(Set<Integer> integers);

    /** * 调用存在已有方法的转换 * * @param cars * @return */
    List<CarDTO> carsToCarDtos(List<CarDO> cars);

    /** * 单个参数的直接使用 * * @param carDO source do * @return target dto */
    @Mapping(target = "userName", constant = "yby")
    @Mapping(target = "modelColor", source = "modelColor", defaultValue = "标致")
    @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss", expression = "java(new Date())")
    CarDTO doToDTO(CarDO carDO);
    
    /** * DTO转为VO * * @param warehouseValidDTOList * @return */
    List<WarehouseValidPageVO> dtoToVo(List<WarehouseValidDTO> warehouseValidDTOList);
}

// mapstruct实现

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2019-07-30T19:27:05+0800",
    comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_101 (Oracle Corporation)"
)
public class CarMapperImpl implements CarMapper { 
   
 
    @Override
    public Set<String> integerSetToStringSet(Set<Integer> integers) { 
   
        if ( integers == null ) { 
   
            return null;
        }

        Set<String> set = new HashSet<String>( Math.max( (int) ( integers.size() / .75f ) + 1, 16 ) );
        for ( Integer integer : integers ) { 
   
            set.add( String.valueOf( integer ) );
        }

        return set;
    }

    @Override
    public List<CarDTO> carsToCarDtos(List<CarDO> cars) { 
   
        if ( cars == null ) { 
   
            return null;
        }

        List<CarDTO> list = new ArrayList<CarDTO>( cars.size() );
        for ( CarDO carDO : cars ) { 
   
            list.add( doToDTO( carDO ) );
        }

        return list;
    }

    @Override
    public CarDTO doToDTO(CarDO carDO) { 
   
        if ( carDO == null ) { 
   
            return null;
        }

        CarDTO carDTO = new CarDTO();

        if ( carDO.getModelColor() != null ) { 
   
            carDTO.setModelColor( carDO.getModelColor() );
        }
        else { 
   
            carDTO.setModelColor( "标致" );
        }
        if ( carDO.getNewCarGuidePrice() != null ) { 
   
            carDTO.setNewCarGuidePrice( BigDecimal.valueOf( carDO.getNewCarGuidePrice() ) );
        }
        carDTO.setBrandCode( carDO.getBrandCode() );
        carDTO.setBrandName( carDO.getBrandName() );
        carDTO.setSeriesCode( carDO.getSeriesCode() );
        carDTO.setSeriesName( carDO.getSeriesName() );
        carDTO.setModelCode( carDO.getModelCode() );
        carDTO.setModelName( carDO.getModelName() );
        carDTO.setModelColorCode( carDO.getModelColorCode() );

        carDTO.setUserName( "yby" );
        carDTO.setCreateTime( new Date() );

        return carDTO;
    }
@Override
    public List<WarehouseValidPageVO> dtoToVo(List<WarehouseValidDTO> warehouseValidDTOList) { 
   
        if ( warehouseValidDTOList == null ) { 
   
            return null;
        }

        List<WarehouseValidPageVO> list = new ArrayList<WarehouseValidPageVO>( warehouseValidDTOList.size() );
        for ( WarehouseValidDTO warehouseValidDTO : warehouseValidDTOList ) { 
   
            list.add( warehouseValidDTOToWarehouseValidPageVO( warehouseValidDTO ) );
        }

        return list;
    }

    protected WarehouseValidPageVO warehouseValidDTOToWarehouseValidPageVO(WarehouseValidDTO warehouseValidDTO) { 
   
        if ( warehouseValidDTO == null ) { 
   
            return null;
        }

        WarehouseValidPageVO warehouseValidPageVO = new WarehouseValidPageVO();

        warehouseValidPageVO.setId( warehouseValidDTO.getId() );
        warehouseValidPageVO.setWarehouseNo( warehouseValidDTO.getWarehouseNo() );
        warehouseValidPageVO.setWarehouseName( warehouseValidDTO.getWarehouseName() );
        warehouseValidPageVO.setPlateValid( warehouseValidDTO.getPlateValid() );

        return warehouseValidPageVO;
    }
}

map

public interface SourceTargetMapper { 
   

    @MapMapping(valueDateFormat = "dd.MM.yyyy")
    Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source);
}

// mapstruct自己实现
@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2019-07-30T19:35:22+0800",
    comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_101 (Oracle Corporation)"
)
public class SourceTargetMapperImpl implements SourceTargetMapper { 
   

    @Override
    public Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source) { 
   
        if ( source == null ) { 
   
            return null;
        }

        Map<String, String> map = new HashMap<String, String>( Math.max( (int) ( source.size() / .75f ) + 1, 16 ) );

        for ( java.util.Map.Entry<Long, Date> entry : source.entrySet() ) { 
   
            String key = new DecimalFormat( "" ).format( entry.getKey() );
            String value = new SimpleDateFormat( "dd.MM.yyyy" ).format( entry.getValue() );
            map.put( key, value );
        }

        return map;
    }
}

案例

Mappings中qualifiedByName属性可以取由@Named声明的名称

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

@Mapper(componentModel = "spring")
public interface UserMapping { 
   

    /** * Student 转化为 User * @param Student * @return */
     @Mappings({ 
   
            @Mapping(target = "uname", source = "sname",qualifiedByName = "booleanToString")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping // ,@Mapping(target = "uname", source = "sname") }) User studentToUser(Student student); @Named("booleanToString")default String booleanToString(boolean value){ if(value){ 
      return "男";    }    return "女"; }}

有的时候有一个额外的转换方法多个mapping类文件都要用到,所以肯定有写一个工具类,mapping引用外部的方法

public class Utils{ 
   
    @Named("booleanToString")
    default String booleanToString(boolean value){ 
    
       if(value){ 
    
          return "男"; 
       } 
       return "女"; 
    }
}
@Mapper(componentModel = "spring",uses=Utils.class)
public interface UserMapping { 
   

    /** * Student 转化为 User * @param Student * @return */
     @Mappings({ 
   
            @Mapping(target = "uname", source = "sname",qualifiedByName = "booleanToString")
    }) 
  User studentToUser(Student student); }

也可以直接使用expression

@Mappings({ 
   
            @Mapping(target = "uname",expression = "java(booleanToString(student.getSname()))")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping // ,@Mapping(target = "uname", source = "sname") 
}) 

多个来源实体转换成一个参数实体

@Mappings({ 
   
    @Mapping(target = "chartName", source = "chart.name"), 
    @Mapping(target = "title", source = "song.title"), 
    @Mapping(target = "artistName", source = "song.artist.name"), 
    @Mapping(target = "recordedAt", source = "song.artist.label.studio.name"), 
    @Mapping(target = "city", source = "song.artist.label.studio.city"), 
    @Mapping(target = "position", source = "position") })
    ChartEntry map(Chart chart, Song song, Integer position);

有一些参数不是来自传入参数,而是默认是一些外部的枚举类或者常量类数据,

就可以在mapper中声明要导入的外部枚举类或者常量类,

@Mapper(componentModel = "spring",
        unmappedTargetPolicy = ReportingPolicy.IGNORE,
        imports = { 
   StringUtils.class,
                UserConsts.class,
                UserStatusEnum.class
}) 

@Mapping(target = "key",expression = "java( UserConsts.FULL_GIFT)"),
@Mapping(target = "status",expression = "java(UserStatusEnum.VALID_STATUS_NO.getCode())"),

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/14290.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信