我有以下 JPA Criteria API 方法:
public List<AggregationTask> findNonExpiredTasksBy(String entityName, Map<String, String> columnValues) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<AggregationTask> query = cb.createQuery(AggregationTask.class);
Root<AggregationTask> root = query.from(AggregationTask.class);
Predicate entityNamePredicate = cb.equal(root.get("edaEntityName"), entityName);
Predicate columnPredicate = cb.conjunction();
if (columnValues != null && !columnValues.isEmpty()) {
List<Predicate> columnConditions = new ArrayList<>();
for (Map.Entry<String, String> entry : columnValues.entrySet()) {
Predicate condition = cb.and(
cb.equal(root.get("edaEntityColumnName"), entry.getKey()),
cb.equal(root.get("edaEntityColumnValue"), entry.getValue())
);
columnConditions.add(condition);
}
columnPredicate = cb.or(columnConditions.toArray(new Predicate[0]));
}
Predicate expiresAtPredicate = cb.greaterThan(root.get("expiresAt"), cb.currentTimestamp());
query.where(cb.and(entityNamePredicate, columnPredicate, expiresAtPredicate));
return entityManager.createQuery(query).getResultList();
}
这会产生以下查询:
select
*
from
aggregation_tasks at1_0
where
at1_0.eda_entity_name =?
and
(
at1_0.eda_entity_column_name =?
and at1_0.eda_entity_column_value =?
or at1_0.eda_entity_column_name =?
and at1_0.eda_entity_column_value =?
or at1_0.eda_entity_column_name =?
and at1_0.eda_entity_column_value =?
or at1_0.eda_entity_column_name =?
and at1_0.eda_entity_column_value =?
or at1_0.eda_entity_column_name =?
and at1_0.eda_entity_column_value =?
or at1_0.eda_entity_column_name =?
and at1_0.eda_entity_column_value =?
)
and at1_0.expires_at > localtimestamp
问题是我需要使用
OR
将以下条件对分组在括号中:
and
(
(at1_0.eda_entity_column_name =? and at1_0.eda_entity_column_value =?)
or
(at1_0.eda_entity_column_name =? and at1_0.eda_entity_column_value =?)
or
(at1_0.eda_entity_column_name =? and at1_0.eda_entity_column_value =?)
or
(at1_0.eda_entity_column_name =? and at1_0.eda_entity_column_value =?)
or
(at1_0.eda_entity_column_name =? and at1_0.eda_entity_column_value =?)
or
(at1_0.eda_entity_column_name =? and at1_0.eda_entity_column_value =?)
)
我的代码做错了什么,我该如何实现这一点?
查询是在没有括号的情况下构建的,这是因为
and
运算符在逻辑(以及 SQL 中)中优先于 or
运算符。在 and
项周围加上括号不会修改条件计算顺序,就像在数学中进行乘法而不是加法时一样。
请同时检查此问题:SQL 逻辑运算符优先级:And 和 Or