繁体   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