Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
framework framework/mapstruct/anti-patterns.md medium

mapstruct-anti-patterns

对象转换的反模式 — 别用反射 BeanUtils.copyProperties、别手写 getter/setter 搬运,枚举映射用 @ValueMapping。Use when 评审对象转换代码 / 看到 BeanUtils 或手写搬运 / 映射枚举时。

转换反模式枚举映射beanutilscopyproperties@valuemappinggetter setter 搬运
paths
  • *.java

MapStruct · 转换反模式

本条只管「别这么干」。Mapper 接口定义见 mapper-definition.md;字段映射见 field-mapping.md

规则

反模式 问题 改用
BeanUtils.copyProperties 反射慢;类型/字段对不上静默漏拷,线上才发现是 null MapStruct Mapper
手写 vo.setX(do.getX()) 逐行搬运 字段一多就漏、改字段两头维护、纯样板 MapStruct 自动生成
枚举 switch/if 手写转换 漏枚举值无提示,新增值忘改 @ValueMapping

核心:这些写法的失败都是静默或滞后的(运行时才暴露),MapStruct 把它们提前到编译期

反例

// ❌ 反射拷贝:amount 类型不一致时静默跳过,不报错
BeanUtils.copyProperties(orderDO, orderVO);

// ❌ 手写搬运:字段一多必漏,新增字段两头改
orderVO.setId(orderDO.getId());
orderVO.setName(orderDO.getName());
// ... 漏了 orderVO.setAmount(...),编译照过

// ❌ 手写枚举 switch:新增 PAID 枚举值忘了加分支,落到 default
String text = switch (status) {
    case CREATED -> "已创建";
    default -> "未知";
};

正例

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface OrderMapper {

    OrderVO toVO(OrderDO source);   // ✅ 自动生成,漏字段编译失败

    // ✅ 枚举映射:@ValueMapping 处理特殊值,其余按名匹配;漏值编译期可控
    @ValueMapping(source = "UNKNOWN", target = MappingConstants.NULL)
    OrderStatusVO toVO(OrderStatusDO status);
}

自检

  • [ ] 没有新增 BeanUtils.copyProperties(Spring 或 Apache 版均不用)?
  • [ ] 没有逐行手写 set/get 搬运对象,而是走 Mapper?
  • [ ] 枚举映射用 @ValueMapping,而非手写 switch/if?

相关