使用Criteria API使用嵌套的JOIN进行复杂的JPA查询

时间:2019-07-17 22:55:56

标签: jpa criteria-api

假设我有一个这样的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

那是将BC连接在一起的结果(加上自定义的ON子句,说明只有C个-与{{1 }}大于零-是可以接受的)。仍然有其他东西分别暴露whateverB(用于使用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值都是空的(根本没有行)。

0 个答案:

没有答案