最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
MapStruct 条件映射:若目标字段非空则执行源字段赋值
时间:2026-07-27 17:00:07 编辑:袖梨 来源:一聚教程网
本文介绍如何在 mapstruct 中实现“仅当目标对象的某个字段不为 null 时,才将源字段映射过去”,避免覆盖已有值,适用于增量更新、dto 合并等场景。
本文介绍如何在 mapstruct 中实现“仅当目标对象的某个字段不为 null 时,才将源字段映射过去”,避免覆盖已有值,适用于增量更新、dto 合并等场景。
在使用 MapStruct 进行对象映射(尤其是 @MappingTarget 增量更新)时,一个常见需求是:仅当目标对象的某字段已有值(非 null)时,才跳过源字段的赋值;反之,若目标字段为 null,则允许从源对象映射新值。但需注意:题中原始诉求“if engine is null, I don't want to map it”实际语义易歧义——通常开发者真正意图是:“当目标 car.engine 已存在(非 null)时,不要用 carDto.device 覆盖它”,即“非空保护式映射”。
MapStruct 本身不支持 @Mapping(whenTargetNotNull = true) 这类原生条件,但可通过组合策略优雅实现:
✅ 推荐方案:使用 @AfterMapping + 显式判空逻辑
@Mapperpublic interface CarMapper { // 先忽略 engine 字段的自动映射 @Mapping(target = "engine", ignore = true) void updateCarFromDto(CarDto carDto, @MappingTarget Car car); // 在映射完成后,按业务逻辑补充处理 @AfterMapping default void handleEngineMapping(CarDto carDto, @MappingTarget Car car) { // 安全校验:防止空指针 if (car == null || carDto == null) { return; } // 关键逻辑:仅当目标 engine 为 null 时,才赋予新值 if (car.getEngine() == null && carDto.getDevice() != null) { car.setEngine(carDto.getDevice()); } // 注:若需“非空时才赋值”,则改为 `car.getEngine() != null` }}
? 提示:上述示例中 if (car.getEngine() == null) 表示“目标为空才映射”,符合多数增量更新场景(如部分字段补全);若需反向逻辑(目标非空才映射),只需调整条件即可。
⚠️ 注意事项与最佳实践
- ignore = true 是必须的:否则 MapStruct 会尝试自动映射 device → engine,覆盖 @AfterMapping 的逻辑;
- @AfterMapping 方法签名必须匹配:参数顺序需与主映射方法一致,且含 @MappingTarget 注解的目标对象;
- 避免副作用:@AfterMapping 中不应修改源对象(carDto),仅操作目标对象(car);
- 考虑 Lombok 兼容性:若 Car 使用 @Data 或 @Setter,确保 setEngine() 可访问;若为不可变类,需改用构造或 Builder 模式;
- 性能提示:该方式引入少量运行时判断,但在绝大多数业务场景中开销可忽略。
✅ 替代方案(高级):使用 @Condition(MapStruct 1.5+)
若项目已升级至 MapStruct 1.5 或更高版本,可利用 @Condition 实现更声明式的条件映射:
@Mapperpublic interface CarMapper { @Mapping(target = "engine", source = "device") void updateCarFromDto(CarDto carDto, @MappingTarget Car car); @Condition default boolean shouldMapEngine(CarDto carDto, @MappingTarget Car car) { return car != null && car.getEngine() == null && carDto != null && carDto.getDevice() != null; }}
此时 shouldMapEngine 将自动被 MapStruct 调用,仅当返回 true 时才执行 device → engine 映射。此方式更简洁、更贴近函数式表达,推荐新项目优先采用。
总之,MapStruct 的条件映射虽无开箱即用的 whenTargetNull 属性,但通过 @AfterMapping 或 @Condition,均可清晰、安全、可维护地实现业务所需的空值保护逻辑。