CriteriaBuilder在谓词中生成了AND而不是OR。

huangapple go评论73阅读模式
英文:

CriteriaBuilder giving AND instead of OR in predicate

问题

以下是翻译好的内容:

我想使用 CriteriaUpdate 查询来更新表中的日期字段。

我正在基于在 where in 子句中过滤的一组 ID 进行此更新。

这组 ID 可能大于1000,因此为了避免 ORA-01795(在 in 子句中的1000限制),我将基于999的子列表对 ID 列表进行了分区。

这是我的代码:

@Modifying
public void updateDate(List<Long> ids, Date date) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaUpdate<MyTable> update = builder.createCriteriaUpdate(MyTable.class);
    Root root = update.from(MyTable.class);
    update.set("dateField", date);	// 在 MyTable 实体中存在 dateField。

    List<List<Long>> partitionedList = Lists.partition(ids, 999);
    List<Predicate> orPredicates = new ArrayList<>();
    partitionedList.forEach(partition -> {
        Predicate predicate = builder.or(root.get("id").in(partition));		// MyTable 实体的 Id
        orPredicates.add(predicate);
    });
    update.where(orPredicates.toArray(new Predicate[]{}));
    entityManager.createQuery(update).executeUpdate();
}

我预期生成的查询应该是这样的:

update myTable set dateField=? where (id in (1, 2, 3.....9999)) OR ((id in (1000, 1001....))

但是生成的查询中有 AND 而不是 OR。

update myTable set dateField=? where (id in (1, 2, 3.....9999)) AND ((id in (1000, 1001....))

我漏掉了什么?

英文:

I want to update a date field in my table using CriteriaUpdate query.

I'm making this update based on the set of IDs filtered in where in clause.

This set of IDs can be greater than 1000, so in order to avoid ORA-01795(1000 limit in in clause), I'm partitioning the IDs list based into sub-lists of 999.

Here is my code:

@Modifying
public void updateDate(List&lt;Long&gt; ids, Date date) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaUpdate&lt;MyTable&gt; update = builder.createCriteriaUpdate(MyTable.class);
    Root root = update.from(MyTable.class);
    update.set(&quot;dateField&quot;, date);	// dateField present in MyTable entity.

    List&lt;List&lt;Long&gt;&gt; partitionedList = Lists.partition(ids, 999);
    List&lt;Predicate&gt; orPredicates = new ArrayList&lt;&gt;();
    partitionedList.forEach(partition -&gt; {
        Predicate predicate = builder.or(root.get(&quot;id&quot;).in(partition));		// Id of MyTable entity
        orPredicates.add(predicate);
    });
    update.where(orPredicates.toArray(new Predicate[]{}));
    entityManager.createQuery(update).executeUpdate();
}

I was expecting generated query to be like:

update myTable set dateField=? where (id in (1, 2, 3.....9999)) OR ((id in (1000, 1001....))

But the generated query has AND instead of OR.

update myTable set dateField=? where (id in (1, 2, 3.....9999)) AND ((id in (1000, 1001....))

What am I missing?

答案1

得分: 3

因为您正在使用Java 8的流逻辑,可以这样做:

update.where(builder.or(
        Lists.partition(ids, 999).stream()
                .map(partition -> root.get("id").in(partition))
                .toArray()
        ));
英文:

Since you're using Java 8 stream logic, do it this way:

update.where(builder.or(
        Lists.partition(ids, 999).stream()
                .map(partition -&gt; root.get(&quot;id&quot;).in(partition))
                .toArray()
        ));

huangapple
  • 本文由 发表于 2020年10月4日 19:29:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/64194054.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定