如何在jpa查询中过滤左连接

时间:2015-07-17 16:28:31

标签: jpa

我遇到了JPA对象无法返回的问题。我有客户和地址,客户可以拥有零个或多个地址。我也软删除项目。此查询有效,除非没有返回地址,否则我不会返回客户详细信息(返回null)。

所以我设置了这样的查询:

select c from Customer c
left join fetch c.createUser 
left join fetch c.lastUpdateUser 
left join fetch c.addressBook a 
where c.id = 1 and c.markForDelete = false 
and (a.id is null or a.markForDelete = false)

如果addressBook中有一行,它会正常工作。但是,如果我删除所有地址,我将无法获得结果。

我在SQL中尝试完成的相当于:

select * from customers c
left join customer_addresses ca
on c.id = ca.customer_id
and c.markForDelete = 0
and ca.markForDelete = 0;

有效并给我一个结果。

2 个答案:

答案 0 :(得分:0)

好的,在这里使用类似的数据,我发现以下查询应该做你想要的:

SELECT DISTINCT c FROM Customer c
LEFT JOIN FETCH c.createUser
LEFT JOIN FETCH c.lastUpdateUser
LEFT JOIN FETCH c.addressBook a
WHERE c.id = 1 AND c.markForDelete = false
AND (SIZE(c.addressBook) = 0 OR a.markForDelete = false)

注意,我发现DISTINCT很重要,否则我会重复数据(客户就是这样)。

此外,返回的具有地址的客户将不会返回该客户的所有地址。附件列表中只有markForDelete为false的地址。

答案 1 :(得分:0)

我得出的结论是,JPA不可能实现这一点。即使使用Hibernate特定的@Where注释,它也很难。

我发现做我想要的唯一方法是“软删除”项目非常直接的情况,是:

  1. 使用特定于Hibernate的@Where(clause =“markForDelete<>'1')注释relationship,而不是相关实体

  2. 请勿使用left join fetch因为它似乎会忽略其他标准,即使它已注释。

  3. 而是使用标准连接,然后从事务中访问属性以触发子查询。

  4. 我想使用软删除几乎使得fetch连接对我来说无法使用...我真的觉得JPA和Hibernate有时很难用。

    有趣的是,根据此页面,EclipseLink似乎支持软删除:https://wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete