HQL 非相关实体的左连接

2022-08-31 22:33:24

我有 2 个实体,并且 .它们是相关的,但我不想将关系映射添加到bean。AB

如何使用 HQL 或标准在 AB 之间使用左外连接

有一些解决方法可用于此,

  1. 按照此处所述使用本机 SQL。
  2. 添加关系并使用从 A 中选择 a 左联接 a.b.
  3. 我们可以在 HQL 中做一个内部连接从 A a 中选择 * ,B b,其中 a.some=b.some

我总是回到这2个选项,有什么替代方案吗?或者这是不可能的?


答案 1

目前,使用 HQL 加入 where 子句中不相关类的 theta 样式仅支持内部连接。

在这种情况下,支持外部连接的请求目前是第3个投票最多的增强功能,但我不认为此功能将在近端功能中实现,因为它需要首先重新实现当前基于ANTLER的查询解析器,这似乎是IMO的一项巨大任务。

如果坚持使用 HQL 执行左连接而不添加 A 和 B 之间的关系,则可以使用选项 3 先执行内部连接,然后使用以下 HQL

from A a where a.some not in ( select b.some from B)

找出所有无法联接 B 的 A,并以编程方式合并结果。

更新

从 5.1.0 版开始,HHH-16(不相关类上的显式连接)已修复,我们应该能够加入不相关的实体。


答案 2

正如Ken Chan所说,你不能直接在单个HQL查询中做到这一点。

关于您的三种可能性:

  1. 本机 SQL:不推荐。不同数据库之间的外联接语法有很大不同。
  2. 添加一个关系:这就是我要做的。它不需要太多的代码或内存,并且可以快速编程。
  3. 内部联接:如果关系确实是数据库中的外联接,则不起作用(缺少行)。

如果由于任何特殊原因,您确实不想添加关系,则可以将查询拆分为两个单独的查询,并在java中手动连接结果,例如:

Query qa = session.createQuery("from A a");
List la = qa.list();

Query qb = session.createQuery("select distinct b.* from B b, A a where a.some=b.some");
List lb = qb.list();

Map bMap = new HashMap();
for (B b : lb) {
  bMap.put(b.getId(), b);
}

/* example with for loop */
for (A a : la) {
  B b = bMap.get(a.getForeignKeyForB());
  /* now you have A a and the outer joined B b and you can do with them what you want */
  ...
}

此解决方案在执行时间和内存方面的成本(几乎)与数据库中的外部联接相同(解决方案 2)。它只是多了一点java代码。

(该解决方案类似于Ken Chan提出的解决方案,但它避免了“不在”和内部选择,这两者在数据库中都可能效率低下。


推荐