首页 > 解决方案 > JPA - 如何实现此 SQL 行为(将父实体左连接到先前内部连接的子实体和大子实体)

问题描述

我无法找到使用 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 查询,将选择部分替换为父项。, 孩子。,孙子。*,但是我也无法正确解析完整的结构:-\

标签: hibernatespring-bootjpajpqlheroku-connect

解决方案


您可以使用FluentJPA进行任何查询,并将其Tuple支持用于投影。向我提供您的实体,我将为您起草完整的解决方案。


推荐阅读