初始情况
使用当前的1.5.0Beta 2 MapStruct版本和JDK 13。
领域模型
class Wrapper { private Fruit fruit; }
abstract class Fruit { private int weight; /* ... */ class Apple extends Fruit { /* ... */ class Banana extends Fruit { /* ... */ }
(相应略去1:1 DTO)
地图绘制者
包装类的Mapper
@Mapper(uses = {FruitMapper.class}) public interface WrapperMapper { WrapperDto map(Wrapper wrapper) }
水果类地图(Es)
具有方法签名和注释的MapStruct Mapper for 抽象 Fruit 类:
Mapper
Fruit
@Mapper(subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION /*...*/) public interface FruitMapper { @SubclassMapping(source = Apple.class, target = AppleDto.class) @SubclassMapping(source = Banana.class, target = BananaDto.class) FruitDto map(Fruit fruit); }
问题
上面的内容可以正常工作,直到需要在引用的抽象类上忽略一个字段(例如, weight 的 Fruit )。将此注释放入 WrapperMapper map 方法..。
weight
WrapperMapper
map
@Mapping(target = "fruit.weight", ignore = true) WrapperDto map(Wrapper wrapper)
...leads到 The return type FruitDto is an abstract class or interface. Provide a non abstract / non interface result type or a factory method. 编译错误。
The return type FruitDto is an abstract class or interface. Provide a non abstract / non interface result type or a factory method.
是否有一种方法可以跳过MapStruct映射中的字段而不获取此编译错误?
发布于 2022-01-02 13:45:36
原因
因为您在WrapperMapper上指定了它,所以它不会直接使用FruitMapper。相反,WrapperMapper实现将得到一个新的映射方法来映射结果。MapStruct在此尝试中失败,并给出了编译错误。
解决方案
如果将该忽略添加到FruitMapper中,它将继承到两个子类映射:
@SubclassMapping( source = Apple.class, target = AppleDto.class ) @SubclassMapping( source = Banana.class, target = BananaDto.class ) @Mapping( target = "weight", ignore = true ) FruitDto map( Fruit fruit );
如果您想要有权重的映射和没有权重的映射,您可以将 @org.mapstruct.Named 注释添加到没有权重的映射中,然后在WrappedMapper中使用该注释。
@org.mapstruct.Named
就像这样:
@Mapper(subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION /*...*/) public interface FruitMapper { @SubclassMapping( source = Apple.class, target = AppleDto.class ) @SubclassMapping( source = Banana.class, target = BananaDto.class ) FruitDto map( Fruit fruit ); @SubclassMapping( source = Apple.class, target = AppleDto.class ) @SubclassMapping( source = Banana.class, target = BananaDto.class ) @Mapping( target = "weight", ignore = true ) @Named( "NoWeights" ) FruitDto map( Fruit fruit );