You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Mapstruct多映射器场景下按条件置空指定字段?

问题说明

需求:当Shipment的status等于Status.Opened时,需将ShipmentResponseDto.cargo.packaging.lastMeasurements的firstField和secondField置为null,逻辑示例如下:

if(shipment.status == Status.Opened){
   ShipmentResponseDto.cargo.packaging.lastMeasurements.firstField = null;
   ShipmentResponseDto.cargo.packaging.lastMeasurements.secondField = null;
}

当前使用ShipmentMapper与CargoPackagingMapper组合映射的方式未实现该逻辑,相关代码结构如下:

@Mapper(uses = {
    CargoPackagingMapper.class
})
public interface ShipmentMapper extends BasicMapper<ShipmentResponseDto, Shipment> {

}

@Mapper(uses = {PackagingTypeMapper.class})
public abstract class CargoPackagingMapper implements BasicMapper<CargoPackagingResponseDto, Packaging> {

    @Override
    @Mappings(...)
    public abstract CargoPackagingResponseDto toDto(Packaging source);
}

public class Shipment {
    // 其他字段
    @Enumerated(EnumType.STRING)
    private Status status;
    private Set<ShipmentCargo> cargo = new HashSet<>();
    // 其他字段
}

public class ShipmentCargo {
    // 其他字段
    @ManyToOne
    private Packaging packaging;
    // 其他字段
}

public class Packaging {
    // 其他字段
    private PackagingLastMeasurements lastMeasurements;
    // 其他字段
}
实现方案

核心思路是将上层Shipment的status作为上下文参数传递给下层的CargoPackagingMapper,让子映射器能根据状态判断是否需要修改字段值,具体实现如下:

1. 修改CargoPackagingMapper,添加带状态参数的映射方法

重载toDto方法接收Shipment的status,并通过@AfterMapping在映射完成后处理字段置空逻辑:

@Mapper(uses = {PackagingTypeMapper.class})
public abstract class CargoPackagingMapper implements BasicMapper<CargoPackagingResponseDto, Packaging> {

    // 暴露Mapper实例,供上层调用
    public static final CargoPackagingMapper INSTANCE = Mappers.getMapper(CargoPackagingMapper.class);

    // 原有基础映射方法
    @Override
    @Mappings({
        // 保留原有字段映射配置
    })
    public abstract CargoPackagingResponseDto toDto(Packaging source);

    // 重载带Shipment状态参数的映射方法
    @Mappings({
        // 继承原有全部映射规则
        @Mapping(target = ".", source = "source")
    })
    public abstract CargoPackagingResponseDto toDto(Packaging source, Status shipmentStatus);

    // 映射完成后置空指定字段的逻辑
    @AfterMapping
    protected void handleOpenedStatusMeasurements(
            @MappingTarget CargoPackagingResponseDto dto,
            Packaging source,
            Status shipmentStatus
    ) {
        if (Status.Opened.equals(shipmentStatus)) {
            // 判空避免NPE
            if (dto.getPackaging() != null && dto.getPackaging().getLastMeasurements() != null) {
                dto.getPackaging().getLastMeasurements().setFirstField(null);
                dto.getPackaging().getLastMeasurements().setSecondField(null);
            }
        }
    }
}

2. 修改ShipmentMapper,传递状态参数给子映射器

自定义集合映射逻辑,遍历ShipmentCargo时将Shipment的status传递给CargoPackagingMapper的重载方法:

@Mapper(uses = {CargoPackagingMapper.class})
public interface ShipmentMapper extends BasicMapper<ShipmentResponseDto, Shipment> {

    @Override
    @Mapping(
            target = "cargo",
            source = "cargo",
            qualifiedByName = "mapCargoWithShipmentStatus"
    )
    ShipmentResponseDto toDto(Shipment source);

    // 自定义集合映射方法,传递Shipment状态
    @Named("mapCargoWithShipmentStatus")
    default List<CargoPackagingResponseDto> mapCargoWithShipmentStatus(
            Set<ShipmentCargo> shipmentCargos,
            Shipment source
    ) {
        return shipmentCargos.stream()
                .map(shipmentCargo -> CargoPackagingMapper.INSTANCE.toDto(
                        shipmentCargo.getPackaging(),
                        source.getStatus()
                ))
                .collect(Collectors.toList());
        // 如果ShipmentResponseDto的cargo是Set类型,替换为Collectors.toSet()
    }
}

说明

  • 通过传递上下文参数(Shipment的status),让子映射器能感知上层对象的状态,实现条件映射逻辑。
  • 使用@AfterMapping确保在基础映射完成后再修改字段值,避免覆盖原有映射结果。
  • 增加判空逻辑防止空指针异常,提升代码健壮性。

内容的提问来源于stack exchange,提问作者Самир Шахмурадлы

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 17:31:15