【发布时间】:2013-03-30 23:53:03
【问题描述】:
问题。如何避免使用 Spring Data REST 进行 n+1 次查询?
背景。在查询 Spring Data REST 以获取资源列表时,每个生成的顶级资源都具有指向关联资源的链接,而不是将关联资源直接嵌入到顶部级资源。例如,如果我查询数据中心列表,相关区域会显示为链接,如下所示:
{
"links" : [ {
"rel" : "self",
"href" : "http://localhost:2112/api/datacenters/1"
}, {
"rel" : "datacenters.DataCenter.region",
"href" : "http://localhost:2112/api/datacenters/1/region"
} ],
"name" : "US East 1a",
"key" : "amazon-us-east-1a"
}
然而,想要获得相关信息而不需要进行 n+1 次查询是非常典型的。为了坚持上面的例子,我可能想在 UI 中显示数据中心及其相关区域的列表。
我已经尝试过。我在 RegionRepository 上创建了一个自定义查询,以获取给定数据中心密钥集的所有区域:
@RestResource(path = "find-by-data-center-key-in")
Page<Region> findByDataCentersKeyIn(
@Param("key") Collection<String> keys,
Pageable pageable);
很遗憾,此查询生成的链接与上述数据中心查询生成的链接不重叠。以下是我为自定义查询获得的链接:
http://localhost:2112/api/regions/search/find-by-data-center-key-in?key=amazon-us-east-1a&key=amazon-us-east-1b
{
"links" : [ ],
"content" : [ {
"links" : [ {
"rel" : "self",
"href" : "http://localhost:2112/api/regions/1"
}, {
"rel" : "regions.Region.datacenters",
"href" : "http://localhost:2112/api/regions/1/datacenters"
}, {
"rel" : "regions.Region.infrastructureprovider",
"href" : "http://localhost:2112/api/regions/1/infrastructureprovider"
} ],
"name" : "US East (N. Virginia)",
"key" : "amazon-us-east-1"
}, {
"links" : [ {
"rel" : "self",
"href" : "http://localhost:2112/api/regions/1"
}, {
"rel" : "regions.Region.datacenters",
"href" : "http://localhost:2112/api/regions/1/datacenters"
}, {
"rel" : "regions.Region.infrastructureprovider",
"href" : "http://localhost:2112/api/regions/1/infrastructureprovider"
} ],
"name" : "US East (N. Virginia)",
"key" : "amazon-us-east-1"
} ],
"page" : {
"size" : 20,
"totalElements" : 2,
"totalPages" : 1,
"number" : 1
}
}
挑战似乎在于,一旦您已经了解了数据的形状,数据中心查询返回的链接信息就不是特别丰富。例如,我已经知道数据中心 1 的区域位于/datacenters/1/region,所以如果我想了解涉及哪个特定区域的实际信息,我必须点击链接获取。特别是,我必须按照链接获取显示在批量查询中的规范 URI,这将允许我避免 n+1 查询。
【问题讨论】:
-
问题不在于 REST,它根本不需要这种方法。问题是您映射到 JSON 的数据模型在任何时候都相当稀疏;它当然不需要那样。 (我更喜欢使用 XML 查询,因为这样我可以更轻松地返回更丰富的结构;我发现能够区分属性和内容在这里很有帮助。)
-
不过,真正的问题是您只是将数据结构放入序列化程序中,而不是计划您实际想要发回的信息以响应每个请求。我认为您可能希望重新访问。
-
同意你的看法 Donal re:一般是 REST。然而,为了澄清,这是 Spring Data REST 框架的工作方式。 (它基于后端实体定义生成 JSON 表示。)当然我可以重新审视我选择的框架,但我想在放弃它之前探索我能用它做什么。
-
我希望看到的是与您提到的内容类似的内容——至少提供规范 URI 作为链接,以便我可以批量查询相关资源,然后通过规范 URI 连接它们。
标签: spring rest spring-data spring-data-rest spring-hateoas