由于各种原因,我试图编写部分动态的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)
如果绝对必须避免动态查询,则可以以另外两个参数为代价:
SELECT customer FROM Customer AS customer JOIN customer.profile AS profile WHERE (profile.status IN :statusCodes OR :statusCodeCount = 0) AND (profile.orgId IN :orgIds OR :orgIdCount = 0)
然后,在Java代码中,您将执行以下操作:
session.getNamedQuery("your.query.name") .setParameterList("statusCodes", statusCodes) .setParameter("statusCodeCount", statusCodes.length) .setParameterList("orgIds", orgIds) .setParameter("orgIdCount", orgIds.length);
您需要确保数组的长度为零,而不是null检查处理null方案时提供其他长度。
null
综上所述,HQL实际上更适合定义明确(例如静态)的查询。您可以解决动态参数,而不能解决动态排序。