JPA Criteria API 和括号

问题描述 投票:0回答:1

我有以下 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 =?)
)

我的代码做错了什么,我该如何实现这一点?

sql jpa spring-data-jpa spring-data jpa-criteria
1个回答
0
投票

查询是在没有括号的情况下构建的,这是因为

and
运算符在逻辑(以及 SQL 中)中优先于
or
运算符。在
and
项周围加上括号不会修改条件计算顺序,就像在数学中进行乘法而不是加法时一样。

请同时检查此问题:SQL 逻辑运算符优先级:And 和 Or

© www.soinside.com 2019 - 2024. All rights reserved.