【问题标题】:@AfterMapping mehod is not called in generated class@AfterMapping 方法未在生成的类中调用
【发布时间】:2022-12-17 23:22:19
【问题描述】:

我正在尝试自定义一个映射,使用一个字符串来确定一个对象属性,所以我这样写:

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class ProductMapper {

public abstract ProductInput asProductInputFromIdentifier(String identifier);

@AfterMapping
protected void determineIdentifier(String identifier, @MappingTarget ProductInput out) {
    if (StringUtils.contains(identifier, '?')) {
        out.setExternalId(identifier);
    } else {
        out.setInernalId(identifier);
    }
}
}

生成的类不调用确定标识符方法。我通过直接使用 Java 表达式找到了另一种解决方案作为 ProductInputFromIdentifier方法,但我真的想使用@AfterMapping.

@Mapping(target = "externalId", expression = "java( org.apache.commons.lang3.StringUtils.contains(identifier, '|') ? identifier : null )")
@Mapping(target = "internalId", expression = "java( !org.apache.commons.lang3.StringUtils.contains(identifier, '|') ? identifier : null )")
public abstract ProductInput asProductDetailInputFromIdentifier(String identifier);

我不明白为什么它不起作用是因为我在方法参数中没有对象吗?

【问题讨论】:

  • 您使用的是哪个版本的 MapStruct?
  • 你好,<org.mapstruct.version>1.4.1.Final</org.mapstruct.version>

标签: mapstruct


【解决方案1】:

@AfterMapping 的方法将在 map 方法的末尾执行,它应该具有与 map 方法相同的输入参数,例如在下面的示例中

@Mapper(
    componentModel = "spring",
    injectionStrategy = InjectionStrategy.CONSTRUCTOR,
    uses = {IdentifierMapper.class})
public interface HistoryMapper {

  HistoryDynamo toHistoryDynamo(History history);

  @AfterMapping
  default void changeReason(History history) {
    System.out.println(history.getReason());
  }
}

请参考 github 工作示例以获得相同的 https://github.com/rakesh-singh-samples/map-struct-samples/tree/stack-question-60523230/src/sample/mapstruct/mapper

【讨论】:

【解决方案2】:

MapStruct 不知道如何从 String 映射到 ProductInput 在你的情况下我建议你自己实现映射方法。

例如

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class ProductMapper {

    public ProductInput asProductInputFromIdentifier(String identifier) {
        ProductInput out = new ProductInput();
        if (StringUtils.contains(identifier, '?')) {
            out.setExternalId(identifier);
        } else {
            out.setInernalId(identifier);
        }
        return out;
    }
}

使用生命周期回调或特殊的 @Mapping 注释来执行此示例中的简单映射是没有意义的。

【讨论】:

  • 您好,它不起作用生成的映射器为空:@Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2022-02-16T11:32:18+0100", cmets = "version: 1.4. 1.Final,编译器:Eclipse JDT (IDE) 1.3.1200.v20200916-0645,环境:Java 11.0.12 (Oracle Corporation)" ) @Component public class ProductMapperImpl extends ProductMapper { }
  • 什么不起作用?没有需要生成的抽象方法,所以实现会是空的
【解决方案3】:

为了解决这个问题,我添加了产品输入抽象方法参数如下(这不是要求)。正如@Rakesh 在他上面的回答中解释的那样@AfterMapping 方法将在 map 方法的末尾执行,它应该与 map 方法具有相同的输入参数,但它可以使其他人对他们的情况感兴趣:

@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public abstract class ProductMapper {

   public abstract ProductInput asProductInputFromIdentifier(String identifier, ProductInput out);

   @AfterMapping
   protected void determineIdentifier(String identifier, @MappingTarget ProductInput out) {
      if (StringUtils.contains(identifier, '?')) {
          out.setExternalId(identifier);
      } else {
          out.setInernalId(identifier);
       }
    }
}

但就我而言,我使用 builder = @Builder(disableBuilder = true) 关闭 MapStruct 中的“builders”,因为它可以帮助某人;)Mapstruct Builder 现在生成的 MapperImpl 调用带注释的@AfterMapping方法。

【讨论】:

    【解决方案4】:

    我遇到过同样的问题。正如@Filip 前面提到的,您的@Aftermapping 方法应该返回与下面给出的映射方法相同的返回类型。

    @AfterMapping
    protected ProductInput determineIdentifier(String identifier, @MappingTarget ProductInput out) {
        if (StringUtils.contains(identifier, '?')) {
            out.setExternalId(identifier);
        } else {
            out.setInernalId(identifier);
        }
    return out;
    }
    

    我面临的问题是,我在返回的对象上使用 Lombok @Builder 注释。当我删除该注释后,我的代码开始正常工作。

    【讨论】:

      猜你喜欢
      • 2019-05-10
      • 2016-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-08
      • 2014-09-05
      • 1970-01-01
      相关资源
      最近更新 更多