3

HQL 菜鸟在这里,真的很挣扎。

可以说我有以下三个类:

public class A {
int id;
B b;
}

public class B {
int id;
Set<C> c;
}

public class C {
int id;
String type;
}

表 B 与 C 具有多对多关系,由表 b_c 定义。我需要一个查询,从表 A 中选择,按 C.id 分组,按 C.type = 'desiredType' 过滤,并返回 C 对象和 A.id 的计数。我一直在玩类似的东西:

SELECT c, COUNT(a.id) as count from A a JOIN a.b.c as c WHERE c.type = 'desiredType' GROUP BY c.id ORDER BY COUNT(a.id) desc

我已经玩过这个查询的不同迭代,但我不断收到各种异常,否则我的查询将不返回任何内容。我似乎不理解的主要问题是如何返回与正确类型匹配的集合的各个对象。

我希望这个问题听起来不愚蠢。我已经阅读了 HQL 手册和其他一百个 SO 问题,但我一定遗漏了一些东西。提前感谢您的任何指导。

4

1 回答 1

2

你想做的事情不会以这种方式工作。最后,您想从 A 和 B 中进行选择,但只选择适合您条件的 Bc 子集。这是不可能的。Hibernate 只能加载完整的集合 c(不是 100% 正确,您可以限制映射中的选择,但这不是这里的解决方案)。这样就有可能无法满足您的要求。您加载所有受 exists 子句限制的 A 并手动计数:

FROM A a where EXISTS (SELECT 1 FROM C, B_C
                          WHERE C.type = 'desiredType'
                             AND B_C.c_id = C.id
                             AND B_C.b_id = a.b.id)

然后,您必须循环遍历列表的所有元素,这些元素是 A 的实例,如果 C 是所需类型,则检查所有 abc 的内部循环(仍然必须完成;上部选择仅限制选择具有至少一个所需类型的 C 的 A,但在您的列表中,您拥有这些 A 的所有 C)并设置正确 c.id 的计数。

该解决方案的缺点是,即使类型错误,也会加载所有 C,并且所有计数都必须在 Java 代码中完成。所以你可能不喜欢那个解决方案。

更好的解决方案是:

从表 C 开始思考。在类 C 中添加一个Set <B> b;(它是多对多关系;也许将连接表 B_C 定义为 Java 类更方便)。在 B 类中,您添加对表 A 的访问,或者添加A a(如果 B:A 是 1:1 关系)或Set<A> a(如果 B:A 是 1:n 关系)。然后您只需选择所需的 C:

FROM C WHERE C.type = 'desiredType'

A group by C.id 您刚刚在 Java 中通过countA = c.b.size()(A 和 B 之间的 1:1 关系)或countA = 0; for (B b : c.b) {countA += b.a.size()}(A 和 B 之间的 n:1 关系)获得的每个选定 c 的计数。

于 2013-03-05T08:04:17.070 回答