Spring Data JPA 获取列表始终返回至少一个结果

Posted

技术标签:

【中文标题】Spring Data JPA 获取列表始终返回至少一个结果【英文标题】:Spring Data JPA fetching list always returns at least a single result 【发布时间】:2021-10-08 05:01:08 【问题描述】:

我注意到我的 API 在我使用 Spring Data JPA 时的工作方式存在一个小问题。 我的查询看起来是这样的:

@Query("SELECT p.id AS id, COUNT(l) AS likes FROM Post p LEFT JOIN Like l ON l.post = p WHERE p.location.id = ?1")

我的实际查询更大,这包含解释问题所在的所有必要内容。此查询将返回一个列表,但假设该位置不存在,它应该返回 null 或空列表,对吗?哦,你错了,我可爱的夏天的孩子! 此查询将始终返回至少包含一个元素的列表,无论是否有任何帖子链接到所述位置。

["id": null, "likes": 0]

这就是序列化为 JSON 时的结果。我不太确定如何处理这个小困境,因为我显然不想返回包含错误数据的列表,但是需要使用处理来过滤掉垃圾似乎也很愚蠢和不必要。 有什么方法可以防止这种我还没有找到吗?如果有任何相关性,我目前正在使用预测作为我的回复。

到目前为止我已经尝试过:

为字段添加非空条件。不起作用,被 COUNT 忽略。 向所有字段@NotNull 添加约束。不起作用,仍然会变为 null。 不管怎样,我尝试了不同类型的连接,但除了 LEFT JOIN 之外的任何连接都没有多大意义。

我也找不到任何其他类似的情况,尽管它很可能存在,但被其他所有情况淹没了。我不太确定在这方面可以做些什么,所以我很好奇这是否只是框架的一个怪癖,或者是否有实际的解决方案。

也许可以通过原生查询来解决,但我不想使用它们。

【问题讨论】:

COUNT(l) 是造成您麻烦的原因。如果它没有找到任何东西,它将按预期计为 0。一种选择是简单地获取后端列表的大小。 @JettoMartínez 更简单的方法是检查第一行是否有空 ID,这正是我现在所倾向于的。这将是一个可靠的解决方案,就好像第一个条目的 ID 为空一样,除非存在格式错误的查询,否则不会有后续行,因为 ID 是主键。遗憾的是,您建议的解决方案也不起作用,因为我的实际查询中也有一个 CASE,尽管它遇到与 COUNT 相同的问题,所以我觉得这没什么大不了的。问题是我需要三个单独的查询才能获得一组结果,这感觉效率很低。 【参考方案1】:

我不是 SQL 专家,但我相信如果 ID 不存在,左连接会给你这个结果。 您是否在数据库中运行查询?对于不存在的 ID,它不会在结果集中为您提供一行吗?

我相信这是说有一个 0 匹配。

您可能希望在运行查询之前对其进行验证。这意味着首先检查该位置是否存在。

【讨论】:

位置存在,没有问题。至于加入,正如我所提到的,我也尝试了不同的加入,但没有成功。通常,如果您无法保证要加入查询的表(在本例中为对象)中存在任何匹配项,则通常需要使用 LEFT JOIN。 INNER JOIN 适用于您要求它同时存在于两者中的情况。还有其他类型的连接,但这两种是我想说的最常见的。问题是 COUNT 总是返回 0 或更高,但即使我在工作中使用 SQL,这根本不是问题,所以它看起来像是一个框架。【参考方案2】:

由于问题本质上是由于我的实际查询中的 COUNT 和 CASE 关键字导致始终存在至少一行,并且我找不到任何自动执行此操作的方法,因此我使用的解决方案是以下:

List<Item> items = repository.customQuery(id);
if (0 < items.size() && null == items.get(0).getId()) 
  items.remove(0);

第一个条件是任意的,因为我知道总是至少有一个条目,但这只是作为一种安全措施。 try-catch 块也可以解决问题。如果您使用原始 int 而不是 Integer,则需要将构造函数中的值初始化为通常不会出现在数据库中的值,例如 -1。

如果有人知道更好的方法,我很想知道。

【讨论】:

以上是关于Spring Data JPA 获取列表始终返回至少一个结果的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA:查询如何返回非实体对象或对象列表?

如何在本机查询中使用 NVL 或 COALESCE 获取 Spring Data JPA 中的值列表

Spring Data JPA 通过查询从实体获取投影

如何在 Spring Data JPA 中获取 countQuery 返回的计数?

外键在一对多关系中始终为空 - Spring Boot Data with JPA

JPA 实体的 Oracle OUT SYS_REFCURSOR 始终为空