简体   繁体   中英

CriteriaBuilder giving AND instead of OR in predicate

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<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);  // dateField present in MyTable entity.

    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));     // 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?

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM