由于各种原因,我正在尝试编写一个部分动态的 HQL 查询而不求助于 Criteria API。我想知道是否有一种简单的方法可以使用 HQL 表达式来短路 where 限制。例如,这是工作正常的原始查询:
SELECT customer
FROM Customer as customer
INNER JOIN customer.profile as profile
WHERE profile.status IN :statusCodes
AND profile.orgId IN :orgIds
StatusCodes 是一个字符串列表,orgIds 是一个整数列表。但是,任何一个都是可选的,并且不应该限制是否传递 null 而不是集合。我试图像这样完成这个:
SELECT customer
FROM Customer as customer
INNER JOIN customer.profile as profile
WHERE (:statusCodes IS NULL OR profile.status IN :statusCodes)
AND (:orgIds IS NULL OR profile.orgId IN :orgIds)
不幸的是,这并没有奏效,但是有没有其他方法可以奏效,要么使用不同的表达式,要么传递默认值?
编辑:为了清楚起见,我正在寻找一种使用 NamedQuery 的方法,而不是以任何方式动态构建查询。
解决方案:我使用了额外的查询参数来完成它。我创建了两个辅助方法:
private void setRequiredParameter(TypedQuery<?> query, String name, Object value) {
query.setParameter(name, value);
}
private void setOptionalParameter(TypedQuery<?> query, String name, Object value) {
query.setParameter(name, value);
query.setParameter(name + "Optional", value == null ? 1 : 0);
}
查询是这样的:
SELECT customer
FROM Customer as customer
INNER JOIN customer.profile as profile
WHERE (:statusCodesOptional = 1 OR profile.status IN :statusCodes)
AND (:orgIdsOptional = 1 OR profile.orgId IN :orgIds)
原文由 ant-depalma 发布,翻译遵循 CC BY-SA 4.0 许可协议
如果你绝对必须避免动态查询,你可以以两个附加参数为代价来做到这一点:
在您的 Java 代码中,您将执行如下操作:
您需要确保数组的长度为零而不是
null
或提供额外的 if 检查来处理null
场景。综上所述,HQL 确实更适合定义明确(例如静态)的查询。您可以解决动态参数问题,但无法解决动态排序问题。