【发布时间】:2021-04-15 08:47:20
【问题描述】:
我有亲子关系。
父类具有以下字段(id, name),子类具有以下列(id, name, date, parent_id)。我想要返回的最终结果 JSON 如下。即使它没有孩子,我也总是想返回父母,这就是为什么我在孩子身上LEFT OUTER JOIN 并带有ON 子句
[
{
"name": "parnet1",
"child": {
"2021-01-01": {
"name": "child1"
},
"2021-01-02": {
"name": "child2"
}
}
},
{
"name": "parnet2",
"child": {}
}
}
]
我的数据库在此示例中的外观示例
parents
id | name
1 | parent 1
2 | parent 2
child
id | name | date | parent_id
1 | child1 | 2021-01-01| 1
2 | child2 | 2021-01-02| 1
3 | child3 | 2020-12-31| 2
对于以下示例,我将传递 2021-01-01 的日期
所以月份是一月 (1),年份是 2021
在父类中,我有一个映射来引用子类
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JsonManagedReference
@MapKey(name = "date")
private Map<LocalDate, Child> children;
这是我的查询
@Query("select p from Parent p left join p.child c on YEAR(c.date) = :dateYear and MONTH(c.date) = :dateMonth
这个问题是休眠后自动运行的第二个查询如下:
select * from Child where c.parent_id = ?
这最终会得到所有连接条件不成立的孩子。
然后我尝试了这个
@Query("select new Parent(p.id, p.name, c.id, c.date, c.name) from Parent p left join p.child c on YEAR(c.date) = :dateYear and MONTH(c.date) = :dateMonth
并制作了这个构造函数
public Parent(int id, String name, int childId, LocalDate date, String childName) {
this.id = id;
this.name = name;
this.children = new HashMap<LocalDate, Child>();
if (childId != null) {
Child child = new Child();
child.setId(id);
child.setName(name);
this.children.put(date, child);
}
}
但问题是,当我希望数组的顶层长度为 2 时,我得到一个长度为 4 的 JSON 数组,因为目前数据库中只有 2 个父级。
如何修改它以获得我想要的 JSON 有效负载,它发布在问题的顶部。
非常感谢
编辑
如果我要传入 date = '2021-01-01',则不会返回 child2,因此使用以下内容不起作用
select distinct p from Parent p
left join fetch p.children c
where (YEAR(c.date) = :dateYear and MONTH(c.date) = :dateMont)
or c.parent is null
EDIT 2(关于自动生成的查询)
我使用 Spring Boot 将其作为 API 运行,但没有额外处理,这是我的 API 和当前查询。
@GetMapping(path = "/parents/{date}", produces = { "application/json" })
@Operation(summary = "Get all parents for date")
public @ResponseBody List<Parent> getParentsByDate(@PathVariable("date") String dateString) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate dateOccurred = LocalDate.parse(dateString, formatter);
return parentRepository.getParentsForDate(dateOccurred);
}
然后在我的存储库中,我只有我的 @Query,这是我目前在 ParentRepository 类中拥有的内容
public interface ParentRepository extends CrudRepository<Parent, Integer> {
@Query("select p from Parent p left join fetch p.children c where (YEAR(c.date) = :dateYear and MONTH(c.date) = :dateMonth) or c.parent is null")
public List<Parent> getParentsForDate(@Param("dateOccurred") LocalDate dateOccurred
}
但正如所说的那样,问题是空检查确实可以正常工作,如果父母在另一个月份有任何孩子,但不是当前的孩子,父母不会返回
【问题讨论】:
-
你在哪个领域加入了他们? YEAR(c.date) = :dateYear 是什么意思?不应该是@Query("select p from Parent p left join p.child c on c.parent_id = p.id WHERE YEAR(c.date) = :dateYear and MONTH(c.date) = :dateMonth?跨度>
-
@MrFisherman 我也总是想返回父级,即使它没有子级,这就是为什么我在子级上使用 ON 子句 LEFT OUTER JOIN,而不是在 WHERE YEAR(c.日期) = :dateYear 和 MONTH(c.date) = :dateMonth。我已经更新了这个问题
-
@iqueqiorio 请指出第二个查询
select * from Child where c.parent_id = ?的生成时间?我的意思是,您是否以任何方式处理实体?例如,您会将它们转换为 JSON 吗? -
@jccampanero 生成第二个查询并在我的查询注释查询之后运行,但我在代码中没有做任何事情来调用它。我正在使用 spring boot 并相信这是生成它我已经发布了第二次编辑
-
非常感谢。我将尝试提供有关该信息的答案。只有一件事:您是否以任何方式使用@Transactional?如果是这样,您能指出在哪里吗?
标签: java sql spring-boot hibernate jpa