gpt4 book ai didi

hibernate - 避免 Grails/Hibernate 中的 N+1 选择

转载 作者:行者123 更新时间:2023-12-02 11:27:09 25 4
gpt4 key购买 nike

更新:可能与 2.0.1 中的这个 Grails 错误有关: http://comments.gmane.org/gmane.comp.lang.groovy.grails.user/125400

更新2:这让我最接近,但分页不起作用。在这种情况下,所有 A 都会返回,每个 A 都有 B 列表,每个 B 都有 C 列表。一旦我添加 offset 和 max,事情就会变得一团糟。例如,在这种情况下,10 个 A 将不会被退回。也许会返回 1 个 A 和 9 个 B。

def results = A.list([fetch:[bees: "eager"], offset: 0, max: 10]);
<小时/>

问题:我想在一个查询中加载所有 A、其关联的 B 以及 B 的关联 C。在一个查询中检索所有 A 及其关联的 B 非常简单。我不知道如何将所有 B 的 C 作为同一单个查询的一部分加载。按照设计,从 B -> C 的默认映射应该是急切的,因为当我加载 B 时我总是需要 C。我认为设置此映射可以解决问题。

class A {
static hasMany = [
bees: B,
]
}

class B {
C c;

static belongsTo = [a: A]

// also tried this and every possible combination
//static fetchMode = [c: 'eager']

static mapping = {
c fetch: 'join'
// c lazy: 'false'
}
}

class C {
String someField;
}

这是我的查询:

def results = A.executeQuery("from A a left join fetch a.bees",
[max: pageSize, offset: offset]);

如果我现在迭代结果:

for (A a in results) {
for (B b in a.bees) {
println "B: " + b; // this is OK, B is already loaded
println "B's C: " + b.c.someField; // C not loaded
}
}

当我迭代结果时,b.c.someField 行将导致每个 B 执行“选择”。这很糟糕,如果可能的话,我想避免这种情况。我发布了一个解决方案作为答案,它使用带有查找 map 的第二个查询,但必须有更好的方法。

我在“更新 2”中发布的查询让我非常接近。事实上,它工作得很好,直到我使用分页(带有偏移量/最大值)。 Grails 用户指南提到“fetch: 'join' 可能会导致带有偏移量/最大值的查询出现问题,但它没有详细说明。注意:为了使此查询正常工作,我必须禁用 hibernate 查询缓存,如中所述由于 Grails 2.0.1 中的错误而导致“更新 1”。

有什么想法吗?

最佳答案

解决方法是简单地获取所有 A 及其关联的 B。

一旦你有了这个,你就可以获取所有 C 的 ID,而无需执行任何查询:

def cIds = [] as Set;

for (A a : results) {
for (B b : a.bees) {
// Note: getCId() is a special method which does not cause a query
cIds.add(b.getCId());
}
}

获得所有 C ID 后,您可以使用第二个查询从数据库中获取这些内容,并将它们存储到 map 中以供稍后查找:

def cMap = [:]
def cees = C.getAll(cIds.toList());
for (C c : cees) {
cMap[c.id] = c;
}

现在,您可以迭代原始结果集以打印出 C 的字段:

for (A a : results) {
for (B b : a.bees) {
println "The meaning of life is " + cMap[b.getCId()].someField;
}
}

查询总数 = 2(一个用于原始左连接,第二个用于获取所有 C)

如果有人有更好的解决方案,请发布。

关于hibernate - 避免 Grails/Hibernate 中的 N+1 选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10540337/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com