繁体   English   中英

使用新的@SubclassMapping 注解时如何忽略 MapStruct 中的某些字段?

[英]How to ignore some fields in MapStruct when using the new @SubclassMapping annotation?

初始情况

使用当前的 1.5.0.Beta2 MapStruct 版本和 JDK 13。

域 Model

class Wrapper {
    private Fruit fruit;
}
abstract class Fruit {
    private int weight;
    /* ... */
}

class Apple extends Fruit {
    /* ... */
}

class Banana extends Fruit {
    /* ... */
}

(相应的 1:1 DTO 省略)

映射器

包装器 class 的映射器

@Mapper(uses = {FruitMapper.class})
public interface WrapperMapper {
    WrapperDto map(Wrapper wrapper)
}

水果类的映射器

带有方法签名和注释的抽象Fruit class 的 MapStruct Mapper

@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);
}

问题

以上工作正常,直到需要在引用的抽象 class 上忽略字段(例如Fruitweight )。 将此注释WrapperMapper map方法...

@Mapping(target = "fruit.weight", ignore = true)
WrapperDto map(Wrapper wrapper)

...导致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 映射中的字段而不会出现此编译错误?

原因

发生的情况是,因为您在 WrapperMapper 上指定了它,所以它不会直接使用 FruitMapper。 相反,WrapperMapper 实现将获得一个新的映射方法,生成到 map 水果。 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 中使用它。

像这样:

    @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 );
    }

    @Mapper(uses = {FruitMapper.class})
    public interface WrapperMapper {
        @Mapping( target = "fruit", qualifiedByName = "NoWeights" )
        WrapperDto map(Wrapper wrapper)
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM