------------恢复内容开始------------
日常开发中,我们时长会写很多关于PO转VO的代码或者是VO转DTO相关的代码,造成我们的程序异常的臃肿。
MapStruct很优雅的帮我们解决了这个问题
一、MapStruct
它是什么?
MapStruct 是一个代码生成器,它基于约定优于配置的方法,极大地简化了 Java bean 类型之间的映射实现。
生成的映射代码使用普通的方法调用,因此速度快、类型安全且易于理解。
为什么要用MapStruct
多层应用程序通常需要在不同的对象模型(例如实体和 DTO)之间进行映射。编写这样的映射代码是一项乏味且容易出错的任务。MapStruct 旨在通过尽可能地自动化来简化这项工作。
与其他映射框架相比,MapStruct 在编译时生成 bean 映射,这确保了高性能,允许快速的开发人员反馈和彻底的错误检查。
例如:
假设我们有一个代表汽车的类(例如一个JPA 实体)和一个伴随的数据传输对象(DTO)。
这两种类型非常相似,只是座位计数属性有不同的名称,并且 type 属性是类中的特殊枚举类型,Car但在 DTO 中是纯字符串。
二、使用mapStruct
要求jdk版本是java8或者更高
Car
public class Car {
private String make;
private int numberOfSeats;
private CarType type;
//constructor, getters, setters etc.
}
CarDto
public class CarDto {
private String make;
private int seatCount;
private String type;
//constructor, getters, setters etc.
}
要生成映射器以从对象中创建CarDto对象Car,需要定义映射器接口:
CarMapper
@Mapper
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}
使用映射器
基于映射器接口,客户端可以以非常简单且类型安全的方式执行对象映射:
@Test
public void shouldMapCarToDto() {
//given
Car car = new Car( "Morris", 5, CarType.SEDAN );
//when
CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
//then
assertThat( carDto ).isNotNull();
assertThat( carDto.getMake() ).isEqualTo( "Morris" );
assertThat( carDto.getSeatCount() ).isEqualTo( 5 );
assertThat( carDto.getType() ).isEqualTo( "SEDAN" );
}
要求jdk版本是java8或者更高
<properties>
<mapstruct.version>1.3.1.Final</mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency>
</dependencies>
可以看到生成的源码:
public class CarMapperImpl implements CarMapper {
@Override
public CarDto carToCarDto(Car car) {
if ( car == null ) {
return null;
}
CarDto carDto = new CarDto();
carDto.setSeatCount( car.getNumberOfSeats() );
carDto.setMake( car.getMake() );
if ( car.getType() != null ) {
carDto.setType( car.getType().name() );
}
return carDto;
}
}
三、 常见用法
(1)两个类型属性不一致
此时CarPo的一个属性为carName,而CarVo对应的属性为name!
我们在接口上增加对应关系即可,如下所示
@Mapper( unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
@Mappings({
@org.mapstruct.Mapping(source = "numberOfSeats", target = "seatCount")})
CarDto carToCarDto(Car car);
}
(2)集合类型转换
从List转换为Lis
CarMapper
@Mapper( unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
@Mappings({
@org.mapstruct.Mapping(source = "numberOfSeats", target = "seatCount")})
CarDto carToCarDto(Car car);
List<CarDto> covertTo(List<Car> videoStreams);
}
CarMapperImpl
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2022-01-16T21:51:16+0800",
comments = "version: 1.4.2.Final, compiler: IncrementalProcessingEnvironment from gradle-language-java-6.8.jar, environment: Java 11.0.13 (JetBrains s.r.o.)"
)
public class CarMapperImpl implements CarMapper {
@Override
public CarDto carToCarDto(Car car) {
if ( car == null ) {
return null;
}
CarDto carDto = new CarDto();
carDto.setSeatCount( car.getNumberOfSeats() );
carDto.setMake( car.getMake() );
if ( car.getType() != null ) {
carDto.setType( car.getType().name() );
}
return carDto;
}
@Override
public List<CarDto> covertTo(List<Car> car) {
if ( car == null ) {
return null;
}
List<CarDto> list = new ArrayList<CarDto>( car.size() );
for ( Car car1 : car ) {
list.add( carToCarDto( car1 ) );
}
return list;
}
}
类型不一致
------------恢复内容结束------------