我有2个实体,A
和B
。它们是相关的,但我不想将关系映射添加到bean。
我们如何使用HQL或条件在A
和B
之间使用左外连接?
有一些可用的解决方法,
我总是回过头来看这两个选项,还有其他选择吗?或者这不可能?
答案 0 :(得分:56)
目前,使用HQL加入where子句中不相关类的theta-style仅支持内连接。
支持此类情况的外部联接的request是currently the 3-rd most voted enhancement但我不认为此功能将在近距离功能中实现,因为它首先需要re-implementation of the current ANTLER-based query parser成为一个巨大的任务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 (Explicit joins on unrelated classes)已修复,我们应该可以加入不相关的实体。
答案 1 :(得分:3)
正如Ken Chan所说,你不能直接在一个HQL查询中完成它。
关于你的三种可能性:
如果由于任何特殊原因您真的不想添加关系,可以将查询拆分为两个单独的查询并在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提出的解决方案,但它避免了“not in”和内部选择,这两者在数据库中都是低效的。)
答案 2 :(得分:1)
如果你知道每个A最多有1个B,你也可以使用子查询。
例如:
select a, (select b from B b where b.some = a.some)
from A a
如果您知道至少存在1个B,您也可以使用以下查询,但不建议这样做,因为它是黑客攻击:
select a, (select b4 from B b4 where b4=b and b4.some=a.some) from A a, B b
where a.some=b.some or (a.some not in (select b2.some from B b2)
and b.id = (select min(b3.id) from B b3))
答案 3 :(得分:-1)
大胆的声明:你不能。
为什么呢? JPQL(和HQL)期望实体之间的路径以加入它们。
我通常在这种情况下做的(首选订单):