我无法找到使用 JPA/JPQL 实现所需结果的方法,因为我使用此 SQL 查询:
select parent.id, child.id, grandchild.id
from salesforce.parent__c parent
left outer join salesforce.child__c child
inner join salesforce.grandchild grandchild on child.grandchild_id__c=grandchild.sfid
and (grandchild.token__c='....')
on parent.sfid=child.parent_id__c
where (parent.external_id__c is not null)
and parent.displayed__c=true
and parent.internal__c=false
and parent.date__c>='....'
and parent.date__c<='....'
order by parent.date__c asc
我正在寻找的查询的目标输出将是这样的:
Parent Child Grandchild
P1 null null
P2 null null
P3 C1 GC1
P4 C2 GC2
来自父级的所有记录都符合父级的过滤器,并且除非其孙子记录符合 gc 的过滤器,否则不会返回子记录。
我对 JPQL 的最佳猜测是这样的
SELECT DISTINCT p FROM Parent p
LEFT JOIN p.childs cl
INNER JOIN cl.grandchilds c
ON c.token__c = '....'
ON cl.parent__c = p.sfid
WHERE p.external_id__c IS NOT NULL
AND p.displayed__c = true
AND p.internal__c = false
AND p.date__c >= '....'
AND p.date__c <= '....'
ORDER BY p.date__c asc
但这是扔org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ON
我做查询的方式我假设是好的:
String queryTxt = "SELECT DISTINCT p FROM Parent p LEFT JOIN p.childs cl INNER JOIN cl.grandchilds c ON c.token__c = '....' ON cl.parent__c = p.sfid WHERE p.external_id__c IS NOT NULL AND p.displayed__c = true AND p.internal__c = false AND p.date__c >= '....' AND p.date__c <= '....' ORDER BY p.date__c asc";
TypedQuery<Parent> typedQuery = entityManager.createQuery(queryTxt, Parent.class);
List<Parent> resultList = typedQuery.getResultList();
如果我尝试使用以下 JPQL,它执行得很好:
SELECT DISTINCT p FROM Parent p
LEFT JOIN p.childs cl
INNER JOIN cl.grandchilds c
ON c.token__c = '....'
WHERE p.external_id__c IS NOT NULL
AND p.displayed__c = true
AND p.internal__c = false
AND p.date__c >= '....'
AND p.date__c <= '....'
ORDER BY p.date__c asc
但结果不是我想要的,因为子孙之间的内部连接也过滤掉了父记录:
Parent Child Grandchild
P3 C1 GC1
P4 C2 GC2
我还尝试Query query = entityManager.createNativeQuery(strQuery, Parent.class);
在帖子开头使用 SQL 查询,将选择部分替换为父项。, 孩子。,孙子。*,但是我也无法正确解析完整的结构:-\