MapStruct - 详细使用(一篇解决MapStruct )

前言

你你是否已经对手动get/set感到厌烦、恶心。什么???你就喜欢写这种代码?那没事了

最近做项目遇到了要做大量的PO,VO,DTO之间的转换,所以一开始想到了Spring BeanUtils 但那个不能进行集合的转换,所以问了我朋友,他给我推荐了MapStruct;

在这里插入图片描述

一、为什么选择MapStruct

工具实现方式缺点说明速度(100w)
MapStructgetter/setter方法需要了解注解和配置项语法JSR269注解处理器在编译期自动生成Java Bean转换代码,支持可配置化,扩展性强54ms
orika动态生成字节码首次调用耗时较久,性能适中采用javassist类库生成Bean映射的字节码,之后直接加载执行生成的字节码文件6764ms
Spring BeanUtils反射机制不支持名称相同但类型不同的属性转换采用javassist类库生成Bean映射的字节码,之后直接加载执行生成的字节码文件6700ms
Apache BeanUtils反射机制需要处理编译期异常,性能最差7086ms
dozer反射机制性能差使用reflect包下Field类的set(Object obj, Object value)方法进行属性赋值6974ms
BeanCopier反射机制BeanCopier只拷贝名称和类型都相同的属性。即便基本类型与其对应的包装类型也不能相互转换使用ASM的MethodVisitor直接编写各属性的get/set方法6834ms

就性能而言:手动get/set > MapStruct > Spring BeanUtils > orika > BeanCopier > dozer > apache BeanUtils

二、MapStruct使用步骤

1、引入依赖

 <!--  mapStruct开始  -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.4.2.Final</version>
    </dependency>
    <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>
    <!--  mapStruct结束  -->

2、新建一个抽象类或者接口并标注@Mapper

在其中写一个转换的方法,方法名字是自定义的
获取对象INSTANCE并使用

	//这是个对象转换的类
	@Mapper
	public abstract class CarConvert(){
		 /**
		     * 提供一个获取CarConvert对象实例的静态属性
			 */
		 public static CarConvert INSTANCE = Mappers.getMapper(CarConvert.class)
		 /**
		     * 对象转换的方法
			 */
		 public abstract CarVo abc(CarDTo carDTo); 
	}

3、测试

  • 其中@Mapper的默认映射规则
  • 同类型且同名的属性,会自动映射
  • 且Mapstruct会自动进行类型的转换
	@Test
	public void test(){
	 CarDTO carDTO = new CarDTO();
	 //直接调用转换的方法,进行对象的转换
	 CarVO carVO = CarConvert.INSTANCE.abc(carDTO);
		System.out.println(carVO)
	}

4、可以通过@Mappings和@Mapping处理映射规则(自定义映射规则)

如果某个属性不想映射给VO,则可以在映射中设置 ignore=true
如果想对已有对象赋值,使用@MappingTarget 注解表示传过来的CarVO对象是已经赋值过的

//这是个对象转换的类
//其中Mapstruct整合spring需要添加一些属性在@Mapping(componentModel = "spring")
@Mapper(componentModel = "spring")
public abstract class CarConvert(){
	//提供一个获取CarConvert对象实例的静态属性(整合spring,这句话就可以不需要了)
	public static CarConvert INSTANCE = Mappers.getMapper(CarConvert.class)
	
    @Mappings(
       value = {
            //指定金额的映射规则,数字格式化numberFormat,保留两位小数
    		@Mapping(source = "totalPrice",target = "totalPrice",numberFormat = "#.00"),
            //指定日期的映射规则,日期格式化dateFormat
   			@Mapping(source = "publishDate",target = "publishDate",dateFormat = "yyyy-MM-dd HH:mm:ss"),
           	//color属性不想映射的设置
            @Mapping(target = "color",ignore = true)
            //属性名不同的映射
            @Mapping(source = “brand”,target = “brandName”)
            //对象里面包含,另一个对象的映射处理
            @Mapping(source = “driverDTO”,target = “driverVO”)
       }
    )
        
    //对象转换的方法对象转换的方法
	public abstract CarVo abc(CarDTo carDTo);	
    
    //对象中 包含的对象 的转换方法
    @Mapping(source = “id”,target = “driverId”)
    @Mapping(source = “name”,target = “fullName”)
    public abstract DriverVO driverDTO2driverVO(DriverDTO driverDTO);
    
    //@AfterMapping 添加这个注解表示mapstruct在调用完自动转换的方法后,会自动调用本方法
    //@MappingTarget 注解表示传过来的CarVO对象是已经赋值过的
    @AfterMapping
    public void dto2voAfter(CarDTO carDTO, @MappingTarget CarVO carVO){
        List<PartDTO> partDTOS = carDTO.getPartDTOS();
        boolean hasPart = partDTOS != null && !partDTOS.isEmpty();
        carVO.setHasPart(hasPart);
    }
    
    //集合对象的批量转换
    public abstract List<CarVo> dto2Vos(List<CarDTO> carDTO);
    
    //@BeanMapping(ignoreByDefault = true) 表示开启  忽略mapstruct的默认映射行为,只有配置了@Mapping注解的才能映射
    @BeanMapping(ignoreByDefault = true)
    @Mapping(source = “id”,target = “id”)
    public abstract VehicleVO carDTO2vehicleVO(CarDTO carDTO);
}

三、遇到的问题

  1. 当出现 Unknown property "xxx" in result type xxx. Did you mean "null"? 错误时添加该依赖:
	<dependency>
	     <groupId>org.projectlombok</groupId>
	     <artifactId>lombok-mapstruct-binding</artifactId>
	     <version>0.2.0</version>
	     <scope>provided</scope>
	</dependency>
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值