ant*_*lma 4 java hibernate hql
我试图编写一个部分动态的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
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用,但是有没有其他方法可以使用,使用不同的表达式或传递默认值?
编辑:只是要明确我正在寻找一种使用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);
}
Run Code Online (Sandbox Code Playgroud)
而查询如下:
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)
Run Code Online (Sandbox Code Playgroud)
我的建议是将所有参数放在一个映射中并构建动态查询,在执行之前构建之后设置查询所需的所有参数从地图中获取值:
Map<String, Object> pars = new HashMap<String,Object>();
pars.put("statusCodes", statusCodes);
pars.put("orgIds", orgIds);
StringBuilder b = "SELECT customer FROM Customer as customer INNER JOIN customer.profile as profile where 1 = 1";
if (statusCodes != null) {
b.append(" and profile.status in :statusCodes");
}
if (orgIds != null) {
b.append(" and profile.orgId in :statusCodes");
}
...
Query q = session.createQuery(b.toString());
...
for (String p : q.getNamedParameters()) {
q.setParameter(p, pars.get(p));
}
Run Code Online (Sandbox Code Playgroud)
当然,例如在未设置参数时抛出异常需要一些改进,如果复杂性大于几个简单参数,则使用类型参数等等.
如果您绝对必须避免动态查询,则可以通过增加两个附加参数来实现:
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)
Run Code Online (Sandbox Code Playgroud)
在 Java 代码中,您可以执行以下操作:
session.getNamedQuery("your.query.name")
.setParameterList("statusCodes", statusCodes)
.setParameter("statusCodeCount", statusCodes.length)
.setParameterList("orgIds", orgIds)
.setParameter("orgIdCount", orgIds.length);
Run Code Online (Sandbox Code Playgroud)
您需要确保数组长度为零,而不是null提供额外的 if 检查来处理null场景。
话虽如此,HQL 确实更适合定义明确的(例如静态)查询。您可以解决动态参数问题,但无法解决动态排序问题。
| 归档时间: |
|
| 查看次数: |
21214 次 |
| 最近记录: |