MapStruct一种映射工具

MapStruct应用于对象属性拷贝,其原理是调用源或目标对象的getter/setter方法实现属性拷贝,而不是使用反射来实现属性拷贝。对于属性是public类型,源/目标对象不必拥有getter/setter方法。其具有以下优点:
1. 对于映射属性类型不匹配,可实现自动转型或指定转型方式
2. 构建时清除错误报告。对于目标对象属性未映射成功,可选多种策略。
使用准备步骤
pom.xml文件中加入引用

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

简单使用

   @Mapper
   public interface TestMapper{
       TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
       @Mappings({@Mapping(target="id",source="testId",ignore=false)})
       UserDTO convert(UserDO userDO);
   }

使用时TestMapper.INSTANCE.convert(xxx)即可将UserDO的属性赋值转换为UserDTO

@Mapper
Mapper注解用来标注某个抽象类或接口是映射器,这个类或接口会被MapStruct实现成对象拷贝的映射器。该注解的主要属性

属性名取值作用默认值
componentModeldefault:映射器不使用组件模型,通常通过实例检索实例 Mappers#getMapper(Class) 。 spring: 生成的映射器上被打了@Compoent注解,若spring注解扫描了此类,可以使用@Autowired等注解获取到映射器实例default
unmappedTargetPolicy目标属性未被映射到时的策略。WARN:发出警告。ERROR:抛出异常。IGNORE:忽略WARN
uses自定义映射类型不匹配时的转型关系映射器{}

@Mappings & @Mapping
用于定义映射关系。若映射关系简单属性类型都互相匹配,则无需使用该注解。只有一个属性需要指明映射关系则直接在该方法上打上@Mapping。对于多个属性需要指明则使用简单使用的代码方式。target是目标属性的意思,source是源目标属性。简单使用的例子是将testId属性映射到id上。ignore决定在target未找到映射时是否忽略,false未不忽略,也是默认选择。

Mappers
Mappers.getMapper(Class<?> clazz)可直接或者映射器的实例。这个方法是固定也是最常用的

自定义方法

   @Mapper
   public interface TestMapper{
       TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
       
       @Mappings({@Mapping(target="id",source="id")})
       UserDTO convert(UserDO userDO);
       /**该方法生成的映射器不会覆盖,对于抽象类中的实例方法也不会被覆盖。由此可以实现一些特殊化的映射方式*/
       default UserDTO convert(UserDO userDO){
         UserDTO userDTO=convert(userDO);
         //操作userDTO,做一些特殊映射
         return userDTO;
       }
       
   }

多源参数映射

   @Mapper
   public interface TestMapper{
       TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
       
       @Mappings({@Mapping(target="name",source="person.name"),@Mapping(target="addressRoad",source="address.road")})
       UserInfo convert(Person person,Address address);
   }

上面将person和address的属性复制给了UserInfo,这里必须要指明映射关系。将address的road属性映射给addressRoad属性。若UserInfo中有个AddressInfo addressInfo属性。AddressInfo中有个road属性。则target=“addressInfo.road”。若UserInfo中有个Address addressTest属性,则最好指定@Mapping(target=“addressTest”,source=“address”)来明确映射关系。

更新目标
上面的例子都是MapStruct为我们创建好了目标对象,有时候目标对象已经存在,我们只需要将一些属性复制给它,可给目标对象打上@MappingTarget

   @Mapper
   public interface TestMapper{
       TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
       
       /**方法上可打上@Mapping来指定映射关系*/
       void update(UserDO userDO,@MappingTarget UserDTO userDTO);
   }

numberFormat & dateFormat
MapStruct支持源映射目标的特殊函数。numberFormat对应java.text.DecimalFormat,dateFormat对应java.text.SimpleDateFormat。它们都是用于源向目标(字符串)的转换

   @Mapper
   public interface TestMapper{
       TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
       
       @Mappings({@Mapping(target="date",source="date",dateFormat="yyyy-MM-dd"),@Mapping(source="salary",target="salary",numberFormat="$##0.00")})
       UserDTO convert(UserDO userDO);
   }

自定义映射
@Mapper的uses属性用来指定隐式的转换映射。

   class A{
      public String dateAsString(Date date){
         return "自定义的转换方式"+date.getTime();
      }
   }
   
   @Mapper(uses=A.class)
   public interface TestMapper{
       TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
       
       @Mappings({@Mapping(target="date1",source="date"})
       UserDTO convert(UserDO userDO);
   }

上例中的userDO中的Date转String会按照A#dateAsString方法进行转换

集合映射
如List<UserDO>转List<UserDTO>,要先定义好UserDO向UserDTO转换的方法。然后定义的List映射方法会按照这个方法进行映射

@Mapper
public interface TestMapper{

   TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
   
  /**UserDO向UserDTO转换的方法*/
  UserDTO convert(UserDO userDO);
  
  /**这个方法就是MapStruct生成的映射方法,不必声明为default,default的代码只是用来说明生成后的效果*/
  default List<UserDTO> convertList(List<UserDO> list){
   List<UserDTO> li=null;
   if(list!=null){
      li=new ArrayList<>();
      list.forEach(c->{
        li.add(convert(c));
      });
   }
   return li;
  }
  
 /**Set的转换,同上*/
 Set<UserDTO> convertSet(Set<UserDO> set);

 /**对于String、Integer这种具有隐式转换的,不必先声明互转方法*/
 List<String> convert2(List<Integer> li);

 /**映射流和映射List一样,利用先定义好的convert方法*/
 List<UserDTO> convertStream(Stream<UserDO> stream);
}

还有@IterableMapping用法

@Mapper
public interface TestMapper{
  TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
  
  @IterableMapping(dateFormat="yyyy/MM/dd")
  List<String> convert(List<Date> dates);
}

映射Map
需要用到@MapMapping注解

@Mapper
public interface TestMapper{
  TestMapper INSTANCE=Mappers.getMapper(TestMapper.class);
  
  @MapMapping(valueDateFormat="yyyy.MM.dd")
  Map<String,String> convert(Map<Long,Date> map);
}

映射枚举
使用@ValueMappings及@ValueMapping,如果两个枚举之间的枚举名称一一对应,则不必使用这两个注解。

@Mapper
public interface TestMapper{
  TestMapper INSTANCE= Mappers.getMapper(TestMapper.class);
  @ValueMappings({
    @ValueMapping(target="B",source="A"),
    @ValueMapping(target="D",source="C")
  })
  Enum2 convert(Enum1 enum1);
}

这样在调用convert(Enum1.A)时会返回Enum2.B。

constant & defaultvalue
constant表示不论源对象中的对应属性值时什么,目标对象的值都是constant的值。defaultvalue表示如果映射关系存在且源对象中属性值为null则使用defaultvalue值代替

@Mapper
public interface TestMapper{
  TestMapper INSTANCE= Mappers.getMapper(TestMapper.class);
  
  @Mapping(target="name",constant="覆盖值")
  UserDTO convert(UserDO userDO);
}

其他映射请见参考文档

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值