假设我有一个这样的SQL:
SELECT a.*
FROM A a
LEFT JOIN
B b
JOIN C c ON (c.b_id = b.id AND c.whatever > 0)
ON (a.id = b.a_id)
现在,我开始使用标准API进行编码:
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<A> criteria = builder.createQuery(A.class);
Root<A> a = criteria.from(A.class);
现在呢?
我还不能Join<A, B> b = a.join("b")
。
应该在定义为a.join(???)
的其他地方调用b
。
那是将B
和C
连接在一起的结果(加上自定义的ON
子句,说明只有C
个-与{{1 }}大于零-是可以接受的)。仍然有其他东西分别暴露whatever
和B
(用于使用C
进行进一步的谓词过滤和/或使用where
进行列投影)。
更新
两者之间有什么区别
(1)select
;和
(2)A a LEFT JOIN (B b JOIN C c ON (c.b_id = b.id AND c.whatever > 0)) ON (a.id = b.a_id)
?
[为清楚起见添加了括号;他们永远不需要]
(A a LEFT JOIN B b ON (a.id = b.a_id)) JOIN C c ON (c.b_id = b.id AND c.whatever > 0)
子句可以理解为“关闭”最后一个“仍然打开”的JOIN。 ON
子句(任何类型)都可以理解为“打开”新的JOIN;这些JOIN堆叠在“打开”上,而堆叠在“关闭”上。
在(1)中,顺序为:I-JOIN(B和C),然后是L-JOIN(A和 that )。 在(2)中,顺序为:L-JOIN(A和B),然后是I-JOIN( that 和C)。
[I-JOIN是一个内部联接,L-JOIN是一个左外部联接]
为简单起见,只需将表C设为空。因此,无论您进行什么JOIN操作,对C(即对其列的引用)的任何引用都将始终为JOIN
。
现在,在(1)中,A中的每一行都会有一个结果。因为I-JOIN(B和C)将始终不产生任何行(请记住,C为空,所以任何INNER JOIN也为空);那么L-JOIN(A和空)将产生A,并且B和C中的所有列都将为NULL。
在(2)中,结果将完全为空。无论L-JOIN(A和B)产生多少行(A的每一行至少有一行),最终的INNER JOIN的C值都是空的(根本没有行)。