问题. 如何在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 查询。