MapStruct 无法从泛型 Set 属性 中找到成员

MapStruct cannot find members from generic Set property

我开始使用 MapStruct 1.4.0.CR1。我也在使用 Gradle:

dependencies {
  annotationProcessor("org.mapstruct:mapstruct-processor:${project.property("mapstruct.version")}")

  implementation("org.mapstruct:mapstruct:${project.property("mapstruct.version")}")
}

我尝试映射一些 JPA 实体:

public class Exam implements Serializable {
  // More class members here

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "exam", orphanRemoval = true)
  private Set<Scan> scans;

  public Exam() { } // ...no-argument constructor required by JPA

  public Exam(final Builder builder) {
    // ...set the rest also
    scans = builder.scans;
  }

  // getters (no setters), hashCode, equals, and builder here
}
public class Scan implements Serializable {
  // More class members here

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "scan", orphanRemoval = true)
  private Set<Alarm> alarms;

  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "scan", orphanRemoval = true)
  private Set<Isotope> isotopes;

  protected Scan() { } // ...no-argument constructor required by JPA

  public Scan(final Builder builder) {
    // ...set the rest also
    alarms = builder.alarms;
    isotopes = builder.isotopes;
  }

  // getters (no setters), hashCode, equals, and builder here
}

我有类似的 class 用于映射,但它们没有 JPA 实体那么多 fields/members,而且,它们位于完全不同的子系统上(因此映射).问题是 MapStruct 告诉我 Scan 内没有 isotopesjava: No property named "scans.isotopes" exists in source parameter(s). Did you mean "scans.empty"?.

基本上,isotopesalarms 不包含在(新)映射的 Exam scansSet 中 class .这是我的 ExamMapper:

@FunctionalInterface
@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface ExamMapper {
  // @Mapping(source = "scans.alarms", target = "alarms")
  @Mapping(source = "scans.isotopes", target = "isotopes")
  Exam valueFrom(tld.domain.Exam entity);
}

有没有办法做到这一点?我认为这可能是微不足道的,但我对 MapStruct 还很陌生 ;)

@Mappingsourcetarget 属性只能引用 bean 属性。

这意味着当使用 scans.isotopes 时,它会在 Set<Scan> 中寻找 属性 isotopes,因此会出现编译错误。

为了解决这个问题,您需要提供一些自定义映射。据我了解,您还需要在此处进行平面映射。原因是你有多次扫描,每次扫描都有多种同位素。您需要收集所有这些并将其映射到一个集合中。

实现此目的的一种方法如下:

@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface ExamMapper {

  @Mapping(source = "scans", target = "isotopes")
  Exam valueFrom(tld.domain.Exam entity);

  Isotope valueFrom(tld.domain.Isotope isotope);

  default Set<Isotope> flatMapIsotopes(Set<Scan> scans) {
    return scans.stream()
        .flatMap(scan -> scan.getIsotopes().stream())
        .map(this::valueFrom)
        .collect(Collectors.toSet());
  }
 
}