一个 springboot 项目,我需要使用父级的指定字段和每个子级的 newest
的指定字段为仪表板 View 构建 DTO。
实体是 Plane
,它与 Transponder、Maint Check 和 Transmitter 具有 OneToMany 关系。
平面
@Entity
@Data
public class Plane {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
private String registration;
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, mappedBy = "plane")
private List<Transponder> listTransponder = new ArrayList<>();
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, mappedBy = "plane")
private List<Transmitter> listTransmitter = new ArrayList<>();
@JsonIgnore
@OneToMany(cascade = CascadeType.ALL, mappedBy = "plane")
private List<MaintCheck> listMaintCheck = new ArrayList<>();
转发器
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Transponder {
@Id
@GeneratedValue(strategy = IDENTITY)
private Long id;
private String code;
private LocalDate dateInserted;
@ManyToOne(fetch = FetchType.LAZY, optional = true)
private Plane plane;
}
Maint Check
和 Transmitter
具有带有 LocalDate 字段的类似实体。
PlaneDTO 看起来像
@Data
public class PlaneDTO {
private String registration;
private LocalDate maintCheck; // date of most recent Maint Check
private String transponderCode; // string of most recent Transponder code
private Integer channel; // Intger of most recent Transmitter Freq
}
我试图在服务层构建这个 PlaneDTO,但我手动对 Transponder、Transmitter 和 Maint Check 列表进行了大部分排序,以从这些列表中获取最新记录。
//DRAFT METHOD CONSTRUCT DTO
@Override
public PlaneSummaryDTO getPlaneSummaryDTOById(Long id) {
Plane Plane = this.get(id);
PlaneSummaryDTO PlaneSummaryDTO = new PlaneSummaryDTO();
ModelMapper mapper = new ModelMapper();
PlaneSummaryDTO = modelMapper.map(get(id), PlaneSummaryDTO.class);
PlaneSummaryDTO.setTRANSPONDERCode(getNewestTRANSPONDERCode(Plane));
PlaneSummaryDTO.setLastMaintCheck(getNewestMaintCheckDate(Plane));
PlaneSummaryDTO.setChannel(getTransmitterCode(Plane));
PlaneSummaryDTO.setChannelOffset(getTransmitterOffset(Plane));
return PlaneSummaryDTO;
}
// RETURN NEWEST DATE OF MAINT CHECK BY CATCH DATE
public LocalDate getNewestMaintCheckDate(Plane Plane) {
List<MaintCheck> listMaintCheck = new ArrayList<>(Plane.getListMaintCheck());
MaintCheck newest = listMaintCheck.stream().max(Comparator.comparing(MaintCheck::getCatchDate)).get();
return newest.getCatchDate();
}
// RETURN NEWEST TRANSPONDER CODE FROM Plane BY DATE INSERTED
public String getNewestTransponderCode(Plane Plane) {
List<Transponder> listTransponder = new ArrayList<>(Plane.getListTransponder());
Transponder newest = listTransponder.stream().max(Comparator.comparing(Transponder::getDateInserted)).get();
return newest.getCode();
}
// OTHER METHODS TO GET MOST RECENT RECORD
问题 有没有更好的方法来计算 child 的最近记录,更有效地使用模型映射器(自定义方法?)
如果 MapStruct 更好地支持获取最新的 child ,我愿意更改为 MapStruct。
最佳答案
我过去曾简单地使用过 ModelMapper。我建议使用 mapstruct,因为我个人觉得它更容易使用。我知道您的映射可以在那里完成;)。在 Mapstruct 中,您的 Mapper 可能看起来像这样:
@MapperConfig(
componentModel = "spring",
builder = @Builder(disableBuilder = true)
)
public interface PlaneMapper {
@Mapping(target = "lastMaintCheck", ignore = true)
PlaneDTO planeToPlaneDTO(Plane plane);
@AfterMapping
default void customCodePlaneMapping(Plane source, @MappingTarget PlaneDTO target) {
target.setLastMaintCheck(source.getListMaintCheck.stream().max(Comparator.comparing(Transponder::getDateInserted)).get())
}
您的映射器调用将只有一行:
@Service
@RequiuredArgsConstructor
public class someService{
private final PlaneMapper planeMapper;
public void someMethod(){
....
PlaneDTO yourMappedPlaneDTO = planeMapper.planeToPlaneDTO(plane);
....
}
我没有填写所有值。但我希望这个概念很清楚。
编辑:
您还必须添加“mapstruct-processor”的依赖项,以便可以生成 MapperImpl 类。
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
关于java - 模型映射器 - 使用自定义方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71823910/