Java项目中实体转化
无处不在,当实体字段较多或许大批量的进行仿制时,经过手工setter/getter显得太LOW,同时兼备高性能要求情况下,MapStruct
彻底彻底能够胜任。官方解说,MapStruct是一个代码生成器,它依据约好优于配置的办法,极大地简化了Java bean类型之间映射的完结。生成的映射代码运用一般办法调用,因此快速、类型安全且易于理解。由于MapStruct是在编译期间生成setter/getter办法,实际运行时便是直接调用setter/getter,效率会非常高。
优点
- MapStruct编译期生成映射代码,所以能够在编译时暴露映射过错的代码,让
过错提早暴露
; - 由于运用
setter/getter
办法,而非反射办法,所以能够更快的执行效率; - 能够完结
深拷贝
,主动类型转化,如枚举转化; - 进行自界说的映射,
多种映射办法
,下边详细说明;
性能比照
比照方针 | 10个方针仿制1次 | 1万个方针仿制1次 | 100万个方针仿制1次 | 100万个方针仿制5次 |
---|---|---|---|---|
MapStruct | 0ms | 3ms | 96ms | 281ms |
Hutools的BeanUtil | 23ms | 102ms | 1734ms | 8316ms |
Spring的BeanUtils | 2ms | 47ms | 726ms | 3676ms |
Apache的BeanUtils | 20ms | 156ms | 10658ms | 52355ms |
Apache的PropertyUtils | 5ms | 68ms | 6767ms | 30694ms |
运用
依赖
<!-- MapStruct中心,包含了一些必要的注解-->
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<!-- MapStruct编译,注解处理器,依据注解主动生成Mapper的完结 -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
界说转化接口
/**
* 测验接口
*
* @author reboot
*/
@Mapper
public interface OrderConvertor {
/**
* 实例
*/
OrderConvertor INSTANCE = Mappers.getMapper(OrderConvertor.class);
/**
* OrderDo -> OrderModel
*
* @param orderDo 订单实体
* @return {@link OrderModel}
*/
OrderModel toModel(OrderDo orderDo);
/**
* OrderDo -> OrderModel
*
* @param orderDos 订单实体
* @return {@link OrderModel}
*/
List<OrderModel> toModel(List<OrderDo> orderDos);
/**
* OrderModel -> OrderDo
*
* @param orderModel 订单模型
* @return {@link OrderDo}
*/
OrderDo toDo(OrderModel orderModel);
/**
* OrderModel -> OrderDo
*
* @param orderModels 订单模型
* @return {@link OrderDo}
*/
List<OrderDo> toDo(List<OrderModel> orderModels);
}
编译成果
MapStruct会主动生成对应接口的完结,并主动完结特点映射联系,List会主动进行批量处理。
调用
/**
* 订单服务
*
* @author reboot
*/
@Service
public class OrderService {
/**
* 获取订单列表
*
* @return {@link List}<{@link OrderModel}>
*/
public List<OrderModel> getOrderList() {
// 获取数据库数据DO
List<OrderDo> result = selectOrderList();
// 参数转化
return OrderConvertor.INSTANCE.toModel(result);
}
}
插件
上边的运用办法尽管能够正常运用,但是在一些特点配置映射上和提示上,如果运用插件能够提升运用体会,IDEA中能够直接安装Mapstruct Support插件,当然Eclipse也有对应的插件。
特性
- 杰出显现方针特点和源特点。将方针特点和源特点转到声明的setter / getter中;
- 过错和快速修正:
-
- 缺少@Mapper或@MapperConfig注解检查;
- 快速修正未映射的方针特点,增加未映射方针特点和忽略未映射方针特点;
其他用法
愈加详细的内容能够检查官方文档,发布文章时最新版本是 MapStruct 1.5.3.Final.html。
根底映射
@Mapper
public interface CarMapper {
@Mapping(target = "manufacturer", source = "make")
@Mapping(target = "seatCount", source = "numberOfSeats")
CarDto carToCarDto(Car car);
@Mapping(target = "fullName", source = "name")
PersonDto personToPersonDto(Person person);
}
target
表明方针特点名,source
表明源特点名,一般在方针特点和源特点不同时运用,相同的特点名会主动进行映射。
映射器增加自界说办法
@Mapper
public interface CarMapper {
@Mapping(...)
...
CarDto carToCarDto(Car car);
default PersonDto personToPersonDto(Person person) {
//hand-written mapping logic
}
}
自界说办法personToPersonDto并完结,在生成的完结类中会进行覆盖
运用。
多个源参数映射
@Mapper
public interface AddressMapper {
@Mapping(target = "description", source = "person.description")
@Mapping(target = "houseNumber", source = "address.houseNo")
DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Address address);
@Mapping(target = "description", source = "person.description")
@Mapping(target = "houseNumber", source = "hn")
DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Integer hn);
}
存在多个源参数,运用参数名.特点名
的办法进行表明,也能够直接运用根底类型
的特点称号。
嵌套特点映射到当时方针
@Mapper
public interface CustomerMapper {
@Mapping( target = "name", source = "record.name" )
@Mapping( target = ".", source = "record" )
@Mapping( target = ".", source = "account" )
Customer customerDtoToCustomer(CustomerDto customerDto);
}
当源参数中存在方针特点,能够手动进行映射,或许直接运用”.”的办法将方针中的特点悉数映射到当时方针方针。
表达式办法
@Mapper
public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mapping(
target = "timeAndFormat",
expression = "java( new org.sample.TimeAndFormat( s.getTime(), s.getFormat() ) )"
)
Target sourceToTarget(Source s);
}
支撑运用java代码块进行转化,一般能够将静态办法处理的字段放到这儿。
更新现有实例
@Mapper
public interface CarMapper {
void updateCarFromDto(CarDto carDto, @MappingTarget Car car);
}
@MappingTarget
源参数,编译时会将carDto参数中的特点映射到car参数中。
Map映射
@Mapper
public interface CustomerMapper {
@Mapping(target = "name", source = "customerName")
Customer toCustomer(Map<String, String> map);
}
直接将map
中的key进行映射。
更多用法
还有更多其他用法,比如:
- 支撑映射界说的public特点;
- 支撑映射参数Builder模式;
- 运用注入办法引入转化器;
- 数据类型字段转化,如枚举、日期,支撑日期格式化,支撑数字类型格式化,详细能够看 Implicit type conversions;
- 集合类型主动转化;
- 转化Stream;
- ……
总结
MapStruct还有许多其他高阶特性,限于篇幅文章只是列举部分示例,有爱好的同学能够检查对应文档试试。运用恰当的东西有用提高编程效率,在运用东西过程中我们也了解其完结原理,不断提高自身。后边有时间也把MapStruct完结原理拿出来讲讲,跟大家一起学习进步!