CriteriaBuilder 和/或条件未应用必需/正确的括号

Posted

技术标签:

【中文标题】CriteriaBuilder 和/或条件未应用必需/正确的括号【英文标题】:CriteriaBuilder and or condition is not applying required/proper parenthesis 【发布时间】:2019-12-30 13:28:04 【问题描述】:

我是这个板的新手。我试图找到解决方案,但找不到解决方案。如果有的话,请分享给我。

    CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
    CriteriaQuery<DmdInventory> criteriaQuery = criteriaBuilder.createQuery(ItemInventory.class);
    Root<ItemInventory> itemRoot = criteriaQuery.from(ItemInventory.class);

    Predicate first = criteriaBuilder.equal(itemRoot.get("margin"), 1.0);
    first = criteriaBuilder.and(first, criteriaBuilder.equal(itemRoot.get("costWithoutExpense"), 1.0));
    first = criteriaBuilder.and(first, criteriaBuilder.equal(itemRoot.get("markup"), 1.0));

    Predicate second = criteriaBuilder.and(criteriaBuilder.equal(itemRoot.get("lastImportCost"), 2.0));
    second = criteriaBuilder.and(second, criteriaBuilder.equal(itemRoot.get("expenses"), 2.0));
    second = criteriaBuilder.and(second, criteriaBuilder.equal(itemRoot.get("profit"), 2.0));

    Predicate third = criteriaBuilder.and(criteriaBuilder.equal(itemRoot.get("totalCost"), 2.0));
    third = criteriaBuilder.and(third, criteriaBuilder.equal(itemRoot.get("cost"), 2.0));
    third = criteriaBuilder.and(third, criteriaBuilder.equal(itemRoot.get("quantity"), 2.0));
    Predicate allPredicate[] =  first, second, third ;
    Predicate finalPredicate = criteriaBuilder.or(allPredicate);

    criteriaQuery.where(finalPredicate);
    List<ItemInventory> items = this.entityManager.createQuery(criteriaQuery).getResultList();

当前结果

 select * from
    item_nventory inven 
where
    inven.last_import_cost=2.0 
    and inven.expenses=2.0 
    and inven.profit=2.0 
    or inven.total_cost=2.0 
    and inven.cost=2.0 
    and inven.quantity=2 
    or inven.margin=1.0 
    and inven.cost_without_expense=1.0 
    and inven.markup=1.0

预期结果

  select * from 
    item_nventory inven 
where
     inven.last_import_cost=2.0 
and inven.expenses=2.0 
and inven.profit=2.0 
or (inven.total_cost=2.0 
and inven.cost=2.0 
and inven.quantity=2 ) 
or (inven.margin=1.0 
and inven.cost_without_expense=1.0 
and inven.markup=1.0)

我的最终要求如下所示

 select * from 
    item_nventory inven 
where
    inven.last_import_cost=2.0 
and inven.expenses=2.0 
and inven.profit=2.0 
or ((inven.total_cost=2.0 
and inven.cost=2.0 
and inven.quantity=2 ) or (inven.quantity_on_hand>0))
or (inven.margin=1.0 
and inven.cost_without_expense=1.0 
and inven.markup=1.0)

请帮帮我。

【问题讨论】:

能否提供您的错误的完整堆栈跟踪。 我没有收到任何错误。我由我的方法的代码提供,除了最后一行是返回语句。运行代码时生成的 SQL。同时我也提供了我想要的输出。 您的Expected result 中似乎有错字:在... and inven.profit=2.0 ( or (inven.total_cost=2.0 ... 下,您的意思是... and inven.profit=2.0 or (inven.total_cost=2.0 ... ?在final requirement 中也是如此? @SternK 感谢您让我知道我的错字。我更正了 SQL。我希望现在要求清楚。 【参考方案1】:

我认为,问题在于谓词的逐步构建。试试下面的构造。

Predicate firstA = criteriaBuilder.equal(itemRoot.get("margin"), 1.0);
Predicate firstB = criteriaBuilder.equal(itemRoot.get("costWithoutExpense"), 1.0);
Predicate firstC = criteriaBuilder.equal(itemRoot.get("markup"), 1.0);
Predicate first = criteriaBuilder.and(firstA, firstB, firstC);

 . . .

Predicate finalPredicate = criteriaBuilder.or(first, second, third);

或带有列表的替代解决方案 - 易于添加或删除另一个谓词(动态事件)

List<Predicate> allPredList = new LinkedList<>();

  List<Predicate> firstPredList = new LinkedList<>();
  firstPredList.add(criteriaBuilder.equal(itemRoot.get("margin"), 1.0));
  firstPredList.add(criteriaBuilder.equal(itemRoot.get("costWithoutExpense"), 1.0));
  firstPredList.add(criteriaBuilder.equal(itemRoot.get("markup"), 1.0));
  allPredList.add(criteriaBuilder.and(firstPredList.toArray(new Predicate[0])));


 . . .

Predicate finalPredicate = criteriaBuilder.or(allPredList.toArray(new Predicate[0]));

【讨论】:

以上是关于CriteriaBuilder 和/或条件未应用必需/正确的括号的主要内容,如果未能解决你的问题,请参考以下文章

如何使 CriteriaBuilder 加入自定义“开启”条件?

JPA CriteriaBuilder in条件构建问题

java-jpa-criteriaBuilder使用入门

Hibernate CriteriaBuilder 加入多个表

JPA / Hibernate:CriteriaBuilder - 如何使用关系对象创建查询?

使用 CriteriaBuilder 的 JPA 计数(*)。如何使用 CriteriaBuilder 检索 count(*) 列