简体   繁体   English

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

[英]how to filter a left join in jpa query

I'm having trouble with a JPA object not being returned. 我在无法返回JPA对象方面遇到麻烦。 I've got customers and addresses, customer can have zero or more addresses. 我有客户和地址,客户可以有零个或多个地址。 I also soft delete items. 我也软删除项目。 This query works, except when there's no addresses returned I don't get the customer details back (returns null ). 该查询有效,除非没有地址返回,但我没有找回客户详细信息(返回null )。

So I set my query like this: 所以我这样设置查询:

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)

It works fine if there's a row in addressBook . 如果addressBook有一行,它会addressBook But if I delete all the addresses I'm getting no result back. 但是,如果删除所有地址,我将无法获得任何结果。

The equivalent of what I'm trying to accomplish in SQL is: 我想要在SQL中完成的任务是:

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

which works and gives me a single result. 这有效,给了我一个结果。

OK, using similar data here, I found the following query should do what you want: 好的,在这里使用类似的数据,我发现以下查询应该执行您想要的操作:

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)

Note, I found that the DISTINCT was important, otherwise I got repeated data (Customers in your case). 注意,我发现DISTINCT很重要,否则我得到了重复的数据(在您的情况下为客户)。

Also, the Customers that are returned which have Addresses will NOT return ALL addresses for that Customer. 另外,返回的具有地址的客户将不会返回该客户的所有地址。 The attached list will only have the Addresses that have markForDelete false. 附加列表将仅具有markForDelete false的地址。

I've come to the conclusion that this is impossible with JPA as it is. 我得出的结论是,对于JPA来说,这是不可能的。 Even with Hibernate specific @Where annotations it's difficult at best. 即使使用特定于Hibernate的@Where注释, @Where也很难。

The only way I found to do what I wanted which is pretty straightforward case of "soft-delete" items, was: 我发现做自己想做的唯一方法是“软删除”项目非常简单的情况,它是:

  1. Annotate the relationship , not the related entity, with Hibernate specific @Where(clause="markForDelete<>'1') 使用特定于Hibernate的@Where(clause =“ markForDelete <>'1')注释relationship ,而不是相关实体。

  2. Do NOT use left join fetch because it seems to ignore the additional criteria even when it's annotated. 不要使用left join fetch因为即使在带注释的情况下,它似乎也会忽略其他条件。

  3. Instead use the standard join ,then access the property from within the transaction to trigger the subquery. 而是使用标准联接,然后从事务内访问属性以触发子查询。

I guess using soft deletes has pretty much rendered fetch joins unusable for me... I really find JPA and Hibernate so frustrating to work with sometimes. 我想使用软删除对我来说几乎无法使用提取连接...我真的发现JPA和Hibernate有时令人沮丧,无法使用。

It's interesting that EclipseLink seems to have support for soft-deletes according to this page: https://wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete 有趣的是,根据此页面,EclipseLink似乎支持软删除: https : //wiki.eclipse.org/EclipseLink/Examples/JPA/SoftDelete

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM