【问题标题】:Mapstruct generated class uses Lombok builder from parent instead of childMapstruct 生成的类使用来自父级而不是子级的 Lombok 构建器
【发布时间】:2020-03-14 16:56:20
【问题描述】:

我有 A 类(域类),B 类(mongo db 存储库层类)扩展了 A,它们都有 Lombok @Builder。我需要在它们之间进行转换,当我为此使用 Mapstruct 时,实现转换类在生成 B 类型的对象时使用来自 A 的 Builder。这会由于“不兼容的类型”而导致构建失败。如何解决这个问题?

@Builder
class A {

}

@Document
@Builder
class B extends A{
}

@Mapper
public interface ClassMapper {
   B mapToDocument(A domainObject);
}

此代码生成以下 Mapstruct 文件:

public class ClassMapperImpl implements ClassMapper{
   @Override
   public B mapToDocument(A domainObject){
      if(domainObject == null){
         return null;
      }
      Builder builder = A.builder();
      //builder methods
      return builder.build(); //incompatible types due to builder generating A objects, not B
   }
}

【问题讨论】:

    标签: java mongodb lombok mapstruct


    【解决方案1】:

    即使没有映射器,您的代码也无法编译。 Lombok 抱怨 B 类中的 @Builder 返回了不兼容的类型:

    返回类型与A.builder()不兼容

    因为.builder()方法是静态的,所以不能使用继承机制。

    另一种解决方案是在A类上使用@Getter,在B类上使用@Setter,让mapstruct为你做映射。

    【讨论】:

      【解决方案2】:

      遇到了同样的问题。通过添加@SuperBuilder 注释来解决它

      【讨论】:

        【解决方案3】:

        @Builder 不能很好地与继承结合使用。但是,mapstruct 也适用于为此类用例设计的 @SuperBuilder

        删除所有@Builders 并将@SuperBuilder 放在继承层次结构中的所有类上。

        【讨论】:

        • 我遇到了同样的问题,但我使用的是 SuperBuilder。当 Mapstructs 生成实现时,它使用父级的构建器。你有暗示吗?
        【解决方案4】:

        可以禁用构建器,请参阅手册https://mapstruct.org/documentation/stable/reference/html/#mapping-with-builders

        如果你想禁用使用构建器,那么你可以通过在 META-INF/services 目录中创建一个 org.mapstruct.ap.spi.BuilderProvider 文件来使用 NoOpBuilderProvider ,因为它是 org.mapstruct.ap.spi.NoOpBuilderProvider内容。

        这解决了问题

        【讨论】:

          猜你喜欢
          • 2020-10-04
          • 2021-10-10
          • 2015-08-14
          • 2013-11-24
          • 2021-05-26
          • 1970-01-01
          • 2021-07-20
          • 2013-07-22
          • 1970-01-01
          相关资源
          最近更新 更多