hibernate - 在 HQL 中选择集合

标签 hibernate collections hql

这里是 HQL 菜鸟,在这个问题上真的很挣扎。

假设我有以下三个类(class):

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 问题,但我一定错过了一些东西。预先感谢您的任何指导。

最佳答案

你想做的事情不会以这种方式进行。最后你想从 A 和 B 中选择,但只选择 B.c 中适合你条件的子集。这不可能。 Hibernate只能加载完整的c集(不是100%正确,您可以限制映射中的选择,但这不是这里的解决方案)。这样就有一种可能性,可能达不到你的要求。您加载受存在子句限制的所有 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 的实例,检查所有 a.b.c 的内部循环,如果 C 是所需的类型(仍然需要完成;上面的select 仅将选择限制为至少具有所需类型的 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'

按 C.id 计算的 A 组计数,您只需在 Java 中为每个选定的 c 获取 countA = c.b.size() (A 和 B 之间为 1:1 关系)或 countA = 0; for (B b : c.b) {countA += b.a.size()} (A 和 B 之间的关系为 n:1)。

关于hibernate - 在 HQL 中选择集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15210651/

相关文章:

java - 通过 Web 应用程序管理 10,000 个用户更新数据库

hibernate - Persistence.createEntityManagerFactory() 需要很长时间才能返回

java - JPA/HQL - 查找具有一对多关系且包含一个或多个特定元素的行

java - hibernate 查询: Get data for Class from joined tables

java - Hibernate QueryTranslatorImpl HQL AST解析性能

java - ORA-00942 : table or view does not exist - Hibernate with non-capital letters

java - 在保存到数据库之前获取 ID

java - 最佳实践 - Collection.add() 和处理 boolean 返回值

Java 集合,无法用新值覆盖旧值

java - 我应该返回什么而不是 null?