MapStruct中目标类使用继承时如何复用已有的Mapper映射逻辑
问题核心
你的复用预期不符合MapStruct的默认运行机制:
- MapStruct的
uses属性仅用于引入其他Mapper中定义的属性级类型转换方法,不会自动复用同入参、目标类为父类的完整对象映射逻辑。 - 当你定义
InventoryResponseV1 toInventoryResponseV1(Inventory inventory)方法时,MapStruct会独立完成Inventory到InventoryResponseV1全量属性的映射,不会自动先调用toInventoryResponse填充父类属性再补充子类属性,因此原有inventoryStatus的映射规则不会被自动继承,才会抛出类型转换错误。
可落地的解决方案
方案1:Mapper继承(最简便)
利用Java协变返回类型特性,让V1版本的Mapper直接继承原有InventoryResponseMapper,父类的映射规则会自动继承生效,仅需补充子类新增属性的映射规则即可:
@JsonInclude(JsonInclude.Include.NON_NULL) @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE) public abstract class InventoryResponseV1Mapper extends InventoryResponseMapper { @Mapping(target = "inventoryId", expression = "java(java.util.UUID.randomUUID())") @Override public abstract InventoryResponseV1 toInventoryResponse(Inventory inventory); }
方案2:使用@InheritConfiguration注解继承映射配置
如果不想用Mapper继承的结构,可以在V1的映射方法上加@InheritConfiguration注解,显式指定继承原有方法的映射配置:
@JsonInclude(JsonInclude.Include.NON_NULL) @Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = {InventoryResponseMapper.class}) public interface InventoryResponseV1Mapper { @InheritConfiguration(name = "toInventoryResponse") @Mapping(target = "inventoryId", expression = "java(java.util.UUID.randomUUID())") InventoryResponseV1 toInventoryResponseV1(Inventory inventory); }
该注解会自动把原有toInventoryResponse方法上的所有@Mapping规则继承到当前方法,无需重复编写父类属性的映射逻辑。
方案3:抽离公共属性转换方法
把InventoryStatus转String的逻辑抽为公共转换类,两个Mapper都引入该类,所有同类属性转换场景都会自动复用该逻辑:
// 公共转换类 public class InventoryStatusMapper { public String map(InventoryStatus status) { return status == null ? null : status.getInventoryStatusCd(); } } // 原有Mapper和V1 Mapper都引入该转换类即可 @Mapper(uses = {InventoryStatusMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE)
内容的提问来源于stack exchange,提问作者Simsons
相关产品推荐
相关产品推荐

