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
内没有 isotopes
:java: No property named "scans.isotopes" exists in source parameter(s). Did you mean "scans.empty"?
.
基本上,isotopes
和 alarms
不包含在(新)映射的 Exam
scans
的 Set
中 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 还很陌生 ;)
@Mapping
的 source
和 target
属性只能引用 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());
}
}
我开始使用 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
内没有 isotopes
:java: No property named "scans.isotopes" exists in source parameter(s). Did you mean "scans.empty"?
.
基本上,isotopes
和 alarms
不包含在(新)映射的 Exam
scans
的 Set
中 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 还很陌生 ;)
@Mapping
的 source
和 target
属性只能引用 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());
}
}