簡體   English   中英

JPA 查詢獲取最近的孩子的孩子

[英]JPA query to get most recent child of child

我有一個包含實體 Plane、MaintenanceCheck、Transponder 的 Soring/JPA 項目。

就 ORM dsetup 而言,Plane 有許多 MaintenanceChecks。 大多數飛機只獲得 1 個轉發器(在維護檢查期間完成),但偶爾飛機可能會更換轉發器。

我還使用 ModelMapper 和 DTO 來查看視圖。

實體

飛機

@Entity
@Data
public class Plane {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    @Column(unique = true)
    private String name;
    @JsonIgnore
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "plane")
    private List<MaintCheck> listMaintCheck = new ArrayList<>();

維護檢查

@Entity
@Data
public class MaintCheck {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private Plane plane;
    private LocalDate checkDate;

    @JsonIgnore
    @OneToMany (cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.MERGE, CascadeType.REFRESH}, orphanRemoval = true, mappedBy = "maintCheck")
    private List<Transponder> listTransponder = new ArrayList<>();

轉發器

@Entity
@Data
public class Transponder {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    private String code;

    @ManyToOne(fetch = FetchType.LAZY, optional = true)
    private MaintCheck maintCheck;

飛機儀表板 DTO

@Data
public class PlaneDashboardDTO {

    private String name;          // plane name
    private LocalDate last_check; // last maintenance date
    private String code;          // most recent transponder code
}

當真正的關系存在於轉發器和飛機之間時,為什么我要以這種方式構建實體(維護檢查恰好發生轉發器更改時)。 因為維護檢查已經有一個日期字段,如果轉發器只通過維護檢查進行更改,那么我最終不會將日期存儲兩次。

TABLE PLANE
ID, NAME
1, NC899
2, N345C

TABLE MAINT CHECK
ID, NAME, DATE, PLANE_ID
1, Check 1, 2022-03-01, 1
2, Check 2, 2022-03-05, 2
3, Check 3, 2022-03-08, 1
4, Check 4, 2022-03-10, 2
5, Check 5, 2022-03-11, 1

TABLE TRANSPONDER
ID, CODE, MAINT_ID
1, DF000AB, 1
2, AB000DC, 3
3, AE000DE, 4

請注意,並非每次維護檢查都有應答器記錄。 事實上大多數不

問題假設這是構造數據的正確方法(我不確定它是)如何將給定平面 ID 的當前(最新)轉發器獲取到 PlaneDashboardDTO 中? (我假設這將在服務層使用 JPQL 或 SQL 完成)

在上面的例子中,我將檢索飛機 ID 1 的最新轉發器,它有維護檢查 ID 1,3, 5。只有維護檢查 1 和 3 在飛機 ID 1 的轉發器表上,因為維護檢查 3 有最近日期,當前轉發器代碼是 AB000DE。

這里有一個小提琴: https://www.db-fiddle.com/f/pxvtyUrQWz3d7s6tdQFT1B/1

如果不在數據庫上進行測試,我會像這樣嘗試 SQL:

select transponder.code
from transponder
join maint_check on maint_check.id=transponder.maint_id
join plane on plane.id=maint_check.plane_id
where plane.id=1
and maint_check.date=(select max(m.date) from maint_check m join transponder t on t.maint_id=m.id and m.plane_id=1)

最后,我決定讓 Transponder 成為 Plane 的直接子代更好。 即飛機(一個)到轉發器(許多)。

然后將數據從 Plane 和 Transponder 獲取到 DTO 的過程位於服務層。

平面服務實現

@Override
public PlaneSummaryDTO getPlaneSummaryDTOById(Long id) {
  Plane plane = this.get(id);
  PlaneSummaryDTO planeSummaryDTO = new PlaneSummaryDTO();
  
    List<Transponder> listTransponder;
    listTransponder = plane.getListTransponder();
    
    Transponder newest = listTransponder.stream().max(Comparator.comparing(Transponder::getDateInserted)).get();
    
    ModelMapper mapper = new ModelMapper();
    planeSummaryDTO = modelMapper.map(get(id), PlaneSummaryDTO.class);
    planeSummaryDTO.setPitCode(newest.getCode());
    return planeSummaryDTO;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM