繁体   English   中英

JPQL:否则将无法正常工作

[英]JPQL: OR won't work as expected

我在存储库中定义了以下方法:

@Query("SELECT t FROM Treatment t WHERE " +
        " (t.promotionCode.promotion.id=:promotionId)  " +
        " order by t.id desc")
Page<Treatment> findByPromotionId(@Param("promotionId")Integer id, Pageable pr);

它按预期工作:我得到了具有属于给定促销的PromotionCode的治疗列表。

但是随后我需要添加第二个促销代码,这样一个Treatment最多可以链接到两个促销(两个促销代码可能属于同一个促销,这不是问题)。 因此,我尝试将新要求添加到查询中:

@Query("SELECT t FROM Treatment t WHERE " +
            " (t.promotionCode.promotion.id=:promotionId)  " +
            " OR " +
            " (t.promotionCode2.promotion.id=:promotionId)  " +
            " order by t.id desc")
Page<Treatment> findByPromotionId(@Param("promotionId")Integer id, Pageable pr);

但是我不会工作。 生成的SQL是

select ...
from treatment treatment0_ 
  cross join promotion_code promotionc1_ 
  cross join promotion_code promotionc2_ 
where 
  treatment0_.promotion_code_id=promotionc1_.id and
  treatment0_.promotion_code2_id=promotionc2_.id and 
  (promotionc1_.promo_id=? or promotionc2_.promo_id=?)
order by 
  treatment0_.id desc limit ?

您会注意到,促销代码之一为空时,将不满足该条件。

即使从代码中可以明显看出一些细节:

  • 除了treatment还有一个名为promotion_code的表和另一个名为promotion
  • 所有表都有数字ID(自动递增)。
  • promotion_code_idpromotion_code2_id处于FKS pointig promotion_code ,其中也有一个FK来promotion ,它不能为空(所有的促销代码属于促销)。

我想找到通过任何促销代码列链接到促销的所有待遇。 两个字段都可以为空。

我该如何解决?

您可以尝试使用条件API。

CriteriaBuilder接口提供了带有两个Expression操作数(包括Predicate实例)并返回一个新Predicate实例的工厂方法:

  Predicate p1 = cb.and(isInUN, isInEU);  // Member of both UN and EU
  Predicate p2 = cb.or(isInOECD, isLarge); // Either OECD member or large

其他工厂方法可用于多种谓词:

  Predicate p3 = cb.and(p1, isLarge, cb.isTrue(isInOECD));
  Predicate p4 = cb.or(p2, cb.isTrue(isInUN), cb.isTrue(isInEU));

在上面的代码中,非谓词布尔表达式使用isTrue方法转换为谓词实例。 这是必需的,因为在非二进制版本中,工厂方法仅接受谓词实例作为参数。

源URL: https : //www.objectdb.com/java/jpa/query/jpql/logical#Criteria_Query_Logical_Operators_

我试图模仿UNION,但效果很好:

SELECT t
FROM Treatment t 
WHERE t IN (SELECT t FROM Treatment t 
      WHERE t.promotionCode.promotion.id = :promotionId)
  OR t IN (SELECT t FROM Treatment t
      WHERE t.promotionCode2.promotion.id = :promotionId)
ORDER BY t.id desc

在此之前,我尝试了LEFT JOIN FETCH选项

SELECT t 
FROM Treatment t 
LEFT JOIN t.promotionCode.promotion as pc
LEFT JOIN t.promotionCode2.promotion as pc2
WHERE 
  (pc.id=:promotionId)  
OR (pc2.id=:promotionId)  
order by t.id desc

SELECT t 
FROM Treatment t 
LEFT JOIN t.promotionCode as pc
LEFT JOIN t.promotionCode2 as pc2
WHERE 
  (pc.promotion.id=:promotionId)  
OR (pc2.promotion.id=:promotionId)  
order by t.id desc

但是它们没有用(我得到了很长的堆栈跟踪,说启动应用程序时查询不正确),

暂无
暂无

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

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