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 中获取 countQuery 返回的计数?