Skip to content

MapStruct对象字段映射

1.MapStruct使用详解

@Mapper注解

目的:为了不再写mapper映射文件

使用:引入依赖

java
    <dependency>
        <groupId>org.mapstruct</groupId>
        <!-- jdk8以下就使用mapstruct -->
        <artifactId>mapstruct-jdk8</artifactId>
        <version>1.2.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>1.2.0.Final</version>
    </dependency>

常见用法

简单属性映射

java
@Mapper
public interface CarMapper {
    @Mapping(target = "manufacturer", source = "make")
    @Mapping(target = "seatCount", source = "numberOfSeats")
    CarDto carToCarDto(Car car);
}

注:简单属性注入支持大部分简单映射,不支持的如日期转String,需要自定义,如:

java
@Mapper
public interface CarMapper {
    // 方法1:指定日期格式
    @Mapping(target = "productionDate", source = "manufactureDate", dateFormat = "yyyy-MM-dd")
    CarDto carToCarDto(Car car);

    // 方法2:自定义逻辑
    @Mapping(target = "productionDate", expression = "java(formatDate(car.getManufactureDate()))")
    CarDto carToCarDto(Car car);

    default String formatDate(Date date) {
        return new SimpleDateFormat("yyyy-MM-dd").format(date);
    }
}

多源参数映射

java
@Mapper
public interface OrderMapper {
    
    @Mapping(target = "customerName", source = "customer.name")
    @Mapping(target = "orderDate", source = "order.orderDate")
    OrderDto toOrderDto(Customer customer, Order order);
}

常量映射

java
@Mapping(target = "category", constant = "SEDAN")
CarDto carToCarDto(Car car);

表达式映射

java
@Mapping(target = "fullName", 
         expression = "java(person.getFirstName() + \" \" + person.getLastName())")
PersonDto personToPersonDto(Person person);

默认值映射

java
@Mapper
public interface CarMapper {
    @Mapping(
        target = "warrantyYears",
        source = "warranty",          // 源字段
        defaultValue = "2",           // 当 source=null 时使用默认值 "2"(转为 Integer)
        defaultExpression = "java(3)" // 当 source=null 时执行表达式返回 3
    )
    CarDto carToCarDto(Car car);
}

忽略特定属性

java
@Mapping(target = "secretCode", ignore = true)
CarDto carToCarDto(Car car);

2.小技巧

数据校验

传统代码校验

java
Assert.isTrue(couponsStatus==null, "优惠券领取已达上限");

注解校验

java
String
	@Size(min = 1, max = 100, message = "标题长度不能为空且长度不能超过100!")
	private String title;
	
Integer
	@NotNull(message = "数量不能为空!")
	@Min(message = "数量不能小于1!", value = 1)
	@Max(message = "数量不能大于500万!")
	private Integer count;
BigDecimal
	@DecimalMin(value = "1.0", message = "总重量必须 ≥1.0")
	private BigDecimal weight;

@NotNull(message = "不能为空")
检查字段是否为 null,但不检查空字符串或空白字符串,适用于所有类型

@NotBlank(message = "不能为空")
仅适用于 String 类型。检查字符串是否非 null、非空字符串("")、非纯空白字符串(" "

这样使用注解还是很麻烦,不同的传入数据,可能需要定义不同的DTO

java
@NotBlank(message = "不能为空", groups = { AddGroup.class, EditGroup.class })

给注解加一个groups分组

java
@PostMapping("/list")
	public PageInfo<SellVO> list(@Validated(AddGroup.class) @RequestBody SellDTO dto) {
		return sellService.getSellList(dto);
	}

在controller层定义的时候使用@Validated(AddGroup.class)来选择使用分组校验,如果不使用分组,则默认校验

本内容仅限内部使用,技术细节以实际代码为准