什么是MapStruct

一种对象之间属性拷贝工具,是基于JSR269实现,能够编译时生成代码,性能高,控制精细,解耦。

在存在大量beanCopy工作时,效率要往往高于一般的BeanCopy工具。

MapStruct性能

映射规则

可以使用接口和抽象类都可以,默认通过@Mapper实现

1
2
3
4
5
6
7
8
9
10
11
12
13
@Mapper
public interface BaseConvert {
BaseConvert INSTANCE = Mappers.getMapper(BaseConvert.class);

BaseDto baseToBaseDto(Base base);
}

@Mapper
public abstract class BaseConvert {
public static BaseConvert INSTANCE = Mappers.getMapper(BaseConvert.class);

public abstract BaseDto baseToBaseDto(Base base);
}

@Mapper

  • 默认映射规则
    • 同名同类型的自动映射
    • 同名不同类型自动类型转换(详细可以看官方MapStruct自动类型转换)
      1. 常用的8种基本数据类型和对应的包装类型会自动转换
      2. 8种基本数据类型和String之间的转换
      3. 日期类型(Date,LocalDate,LocalTime等)和String之间的转换

@Mappings和@Mapping

  • 指定属性之间的映射关系
    • 日期格式化
    • 数字格式化
  • Ignore忽略字段不拷贝
  • 不同名字可以拷贝
  • 集合拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

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

/**
* Base -> BaseDTO
*
* @param base Base
* @return BaseDto
*/
@Mappings(
value = {
// double -> string 保留2位小数
@Mapping(source = "number", target = "number", numberFormat = "#.00"),
// date -> string 日期
@Mapping(source = "time", target = "time", dateFormat = "yyyy-MM-dd HH:mm:ss"),
// 忽略不要id
@Mapping(target = "id", ignore = true),
// 源对象属性msg 赋值到目标对象属性msgString
@Mapping(source = "msg", target = "msgString")
}
)
BaseDto baseToBaseDto(Base base);

/**
* List Base -> List BaseDto
*
* @param baseList List Base
* @return List BaseDto
*/
List<BaseDto> baseListToBaseDtoList(List<Base> baseList);
}

@AfterMapping和@MappingTarget

自定义属性转换,表示在mapstruct调用完自动转换的方法后,会来自动调用本方法

1
2
3
4
5
6
7
8
9
10
11
12
/**
* Base -> BaseDTO
*
* @param base Base
* @param baseDto BaseDTO
* @AfterMapping 表示在调用完后执行
* @MappingTarget 表示目标对象
*/
@AfterMapping
default void afterBaseToBaseDto(Base base, @MappingTarget BaseDto baseDto) {
System.out.println("in AfterMapping..");
}

@BeanMapping

可以只更新规定的字段,或一些copy时的一些配置,@BeanMapping功能较多,有时间一一列举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Mapper
public interface BaseConvert {
BaseConvert INSTANCE = Mappers.getMapper(BaseConvert.class);

/**
* Base -> BaseDTO
* 只更新配置mapping的
* @param base Base
* @return BaseDTO
*/
@BeanMapping(ignoreByDefault = true)
@Mapping(source = "id", target = "id")
BaseDto beanMappingBaseToBaseDto(Base base);
}

@InheritConfiguration()和@InheritInverseConfiguration

@InheritConfiguration:继承配置,用于多个对象转换方法相同进行配置

@InheritInverseConfiguration:反向继承配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Mapper
public interface BaseConvert {
BaseConvert INSTANCE = Mappers.getMapper(BaseConvert.class);

@BeanMapping(ignoreByDefault = true)
@Mapping(source = "id", target = "id")
@Mapping(source = "msg", target = "msgString")
BaseDto beanMappingBaseToBaseDto(Base base);

/**
* 继承beanMappingBaseToBaseDto配置
* @param base
* @return
*/
@InheritConfiguration(name = "beanMappingBaseToBaseDto")
BaseDto otherBaseToBaseDto(Base base);

/**
* 反向继承beanMappingBaseToBaseDto配置
* @param baseDto
* @return
*/
@InheritInverseConfiguration(name = "beanMappingBaseToBaseDto")
Base baseDtoToBase(BaseDto baseDto);
}

更新空值忽略

1
2
3
4
5
6
7
8
/**
* 更新时空值忽略
*
* @param base Base
* @param baseDto BaseDTO
*/
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void updateBaseDtoByBase(Base base, @MappingTarget BaseDto baseDto);

和spring结合使用

1
2
3
4
// 默认default
// 可以通过修改componentModel为spring使用
// 可以通过注入使用
@Mapper(componentModel = "spring")