一 PO VO DTO 是什么
二 mapStruct
官网链接: https://mapstruct.org/documentation/dev/reference/html/.
2.1 导入依赖
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.3.1.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.3.1.Final</version>
</dependency>
2.2 准备数据传输对象DTO
@Data
public class CarDTO {
private Long id;
private String vin;
private double price;
private double totalPrice;
private Date publishDate;
private String color;
private String brand;
private List<PartDTO> partDTOS;
private DriverDTO driverDTO;
}
@Data
public class DriverDTO {
private Long id;
private String name;
}
@Data
public class PartDTO {
private Long partId;
private String partName;
}
2.3 准备值对象VO
@Data
public class CarVO {
private Long id;
private String vin;
private Double price;
private String totalPrice;
private String publishDate;
private String brandName;
private String color;
private Boolean hasPart;
private DriverVO driverVO;
}
@Data
public class DriverVO {
private Long driverId;
private String fullName;
}
@Data
public class PartVO {
private Long partId;
private String partName;
}
@Data
public class VehicleVO {
private Long id;
private Double price;
private String brandName;
}
2.4 新建一个抽 象类或者接口并标注@Mapper (构造一个INSTANCE )
/**
* 使用mapstruct 的步骤:
* 1.引入依赖
* 2.新建一个抽 象类或者接口并标注@Mapper
* 3.写一个方法
* 4.获取对象并使用
* 5.相关的pojo之间的转化
*/
@Mapper(componentModel = "spring")
public abstract class CarConvert {
public static CarConvert INSTANCE = Mappers.getMapper(CarConvert.class);
/**
* CarDto-- >CarVo
*/
@Mappings(value = {
@Mapping(source = "totalPrice", target = "totalPrice", numberFormat = "#.OO"),
@Mapping(source = "publishDate", target = "publishDate", numberFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "color", ignore = true),
@Mapping(source = "brand", target = "brandName"),
@Mapping(source = "driverDTO", target = "driverVO")
})
public abstract CarVO Dto2Vo(CarDTO carDTO);
@Mapping(source = "id", target = "driverId")
@Mapping(source = "name", target = "fullName")
public abstract DriverVO driverDTO2DriverVO(DriverDTO driverDTO);
@AfterMapping //表示mapstruct 在调用完自动转换的方法之后,会来自动调用本方法
public void dto2voAfter(CarDTO carDTO, @MappingTarget CarVO carVO) {
// @MappingTarget :表示传来的carVO对象是已经赋值过的
List<PartDTO> partDTOS = carDTO.getPartDTOS();
boolean hasPart = partDTOS != null && !partDTOS.isEmpty();
carVO.setHasPart(hasPart);
}
/**
* dto2vo这个方法的批量转换
*/
public abstract List<CarVO> dtos2vos(List<CarDTO> carDTO);
// @Mapping(source = "price" ,target = "price",ignore = true)
@BeanMapping(ignoreByDefault = true)
@Mapping(source = "id", target = "id")
// @Mapping(source = "price" , target = "price" , numberFormat = "#.00")
@Mapping(source = "brand", target = "brandName")
public abstract VehicleVO carDTO2vehicleVO(CarDTO carDTO);
// @BeanMapping(ignoreByDefault = true)
// @Mapping(source = "id",target = "id")
// @Mapping(source = "brand" , target = "brandName")
@InheritConfiguration
@Mapping(target = "id", ignore = true)
public abstract void updateVehicleVO(CarDTO carDTO, @MappingTarget VehicleVO vehicleVO);
/**
* 测试@InheritInverseConfigurat ion反向继承
* name:指定使用哪一个方法的配置,
* @param vehicleVO
* @return
*/
@BeanMapping(ignoreByDefault = true)
// @Mapping(source = "id" ,target = "id")
// @Mapping(source = "brandName" ,target = "brand")
@InheritInverseConfiguration(name = "carDTO2vehicleVO")
@Mapping(target = "id", ignore = true)
public abstract CarDTO vehicleVO2CarDTO(VehicleVO vehicleVO);
}
2.5 Test
public class MapStructTest {
/*
* 测试传统的通过getter.和Isetter赋值完成pojo之间转换
* CarDto-->CarVo
*/
@Test
public void test1() {
//模拟业务构造出的CarDTO对象
CarDTO carDto = buildCarDTO();
CarVO carVO = new CarVO();
carVO.setId(carDto.getId());
carVO.setVin(carDto.getVin());
carVO.setPrice(carDto.getPrice()); //装箱拆箱机制,不需要我们自己转化
double totalPrice = carDto.getTotalPrice();
DecimalFormat df = new DecimalFormat("#.00");
String totalPriceStr = df.format(totalPrice);
carVO.setTotalPrice(totalPriceStr);
Date publishDate = carDto.getPublishDate();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String publishDateFormat = sdf.format(publishDate);
carVO.setPublishDate(publishDateFormat);
carVO.setBrandName(carDto.getBrand());
carVO.setColor(carDto.getColor());
List<PartDTO> partDTOS = carDto.getPartDTOS();
boolean hasPart = partDTOS != null && !partDTOS.isEmpty();
carVO.setHasPart(hasPart);
DriverVO driverVO = new DriverVO();
DriverDTO driverDTO = carDto.getDriverDTO();
driverVO.setDriverId(driverDTO.getId());
driverVO.setFullName(driverDTO.getName());
carVO.setDriverVO(driverVO);
System.out.println(carVO);
}
private CarDTO buildCarDTO() {
CarDTO carDTO = new CarDTO();
carDTO.setId(330L);
carDTO.setVin("vin123456789");
carDTO.setPrice(123789.126d);
carDTO.setTotalPrice(143789.126d);
carDTO.setPublishDate(new Date());
carDTO.setBrand("大众");
carDTO.setColor("白色");
//零件
PartDTO partDTO1 = new PartDTO();
partDTO1.setPartId(1L);
partDTO1.setPartName("多功能方向盘");
PartDTO partDTO2 = new PartDTO();
partDTO2.setPartId(2L);
partDTO2.setPartName("智能车门");
List<PartDTO> partDTOList = new ArrayList<>();
partDTOList.add(partDTO1);
partDTOList.add(partDTO2);
carDTO.setPartDTOS(partDTOList);
//设置驾驶员
DriverDTO driverDTO = new DriverDTO();
driverDTO.setId(88L);
driverDTO.setName("小明");
carDTO.setDriverDTO(driverDTO);
return carDTO;
}
@Test
public void test2() {
CarDTO carDto = buildCarDTO();
CarVO carVO = CarConvert.INSTANCE.Dto2Vo(carDto);
System.out.println(carVO);
}
/**
* 测试mapstruct
* List<CarDto>--> List<CarVo>
*/
@Test
public void test3() {
CarDTO carDTO = buildCarDTO();
List<CarDTO> carDTOList = new ArrayList<>();
carDTOList.add(carDTO); // source
// target
List<CarVO> carVOList = new ArrayList<>();
for (CarDTO dto : carDTOList) {
CarVO carVO = CarConvert.INSTANCE.Dto2Vo(carDTO);
carVOList.add(carVO);
System.out.println(carVOList);
}
}
@Test
public void test4() {
CarDTO carDTO = buildCarDTO();
List<CarDTO> carDTOList = new ArrayList<>();
carDTOList.add(carDTO); // source
List<CarVO> carVOList = CarConvert.INSTANCE.dtos2vos(carDTOList);
System.out.println(carVOList);
}
/**
* 测试@BeanMapping
*/
@Test
public void test5() {
CarDTO carDTO = buildCarDTO();
VehicleVO vehicleVO = CarConvert.INSTANCE.carDTO2vehicleVO(carDTO);
System.out.println(vehicleVO);
}
/**
* 测试@BeanMapping
*/
@Test
public void test6() {
CarDTO carDTO = buildCarDTO();
VehicleVO vehicleVO = CarConvert.INSTANCE.carDTO2vehicleVO(carDTO);
CarDTO carDTO2 = new CarDTO();
// carDTO2.setId(330L);
carDTO2.setBrand("迈巴赫");
//通过carDTO2的属 性值来更新已存在的vehicleVO对象
CarConvert.INSTANCE.updateVehicleVO(carDTO2, vehicleVO);
System.out.println(vehicleVO);
}
/**
* 测试@InheritInverseConfiguration反向继 承
*/
@Test
public void test7() {
VehicleVO vehicleVO = new VehicleVO();
vehicleVO.setId(9999L);
vehicleVO.setBrandName("别克");
vehicleVO.setPrice(66554322d);
CarDTO carDTO = CarConvert.INSTANCE.vehicleVO2CarDTO(vehicleVO);
System.out.println(carDTO);
}
// @Autowired
@Resource
private CarConvert carConvert;
/**
* 测试mapstruct 和spring整合
*/
@Test
public void test8() {
VehicleVO vehicleVO = new VehicleVO();
vehicleVO.setId(9999L);
vehicleVO.setBrandName("别克");
vehicleVO.setPrice(66554322d);
CarDTO carDTO = carConvert.vehicleVO2CarDTO(vehicleVO);
System.out.println(carDTO);
}
}
三 总结
3.1 @AfterMapping和@MappingTarget·在映射最后一步对属性的自定义映射处理
@AfterMapping //表示让mapstruct在调用完自动转换的方法之后,会来自动调用本方法
@MappingTarget :表示传来的对象是已经赋值过的
3.2 @BeanMapping
ignoreByDefault :忽略mapstruct的默认映射行为,只映射那些配置了@Mapping的属性。避免不需要的赋值、避免属性覆盖
3.3 @InheritConfiguration
·更新的场景,避免同样的配置写多份
3.4 @InheritInverseConfiguration
@InheritInverseConfiguration反向继承 name:指定使历哪一个方法的配置
·反向映射不用反过来再写—遍,注意:只继承@Mapping注解配置,不会继承@BeanMapping
3.5 与spring结合使用
@Mapper(componentModel = “spring”)//实质就是给生成的类加了@component