10

I have a List to append in an or condition

The Issue I am facing is when I am iterating over the List and adding it to the CategoryBuilder then it takes the last Predicate

Following is the example:

public static Specification<Billoflading> hasTenantAndBillingCodeCombination(List<WhoOwnsIt> list,
            Date formattedFromDate, Date formattedToDate, String carrierFilter, String supplierFilter,
            String terminalFilter) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            for (WhoOwnsIt whoOwnsIt : list) {
                String containsLikePatternForTenant = getContainsLikePattern(whoOwnsIt.getWholesalerTenantID(), true);

                Predicate pred = cb.and(cb.like(cb.lower(root.<String>get("tenant")), containsLikePatternForTenant),
                        cb.equal(cb.lower(root.<String>get("billingCode")), whoOwnsIt.getBillingCode()),
                        cb.greaterThanOrEqualTo(root.<Date>get("scheduleDate"), formattedFromDate),
                        cb.lessThanOrEqualTo(root.<Date>get("scheduleDate"), formattedToDate));

                Predicate predWithTenant = null;

                if (null != carrierFilter) {
                    predWithTenant = cb.and(cb.equal(cb.lower(root.<String>get("tenant")), carrierFilter));
                }

                if (null != predWithTenant)
                    predicates.add(predWithTenant);
                else
                    predicates.add(pred);

            }
            Predicate finalPredicate;
            // This commented section below needs to be replaced with a 
            //better solution
            //for(Predicate predicate : predicates){
            //  cb.or(predicate);
            //}

            return finalPredicate;
        };
    }

I also tried making the List an array for passing it to the finalPredicate.or as follows

Predicate finalQuery = cb.or(predicates.toArray());

But this code gave compilation error as the parameters needed is varargs i.e.

or method accepts (Predicate... predicates) as parameter list

Can you please provide some simple solution to this issue?

Kalyan Pradhan
  • 1,415
  • 3
  • 19
  • 34

3 Answers3

33

Try this:

Predicate finalQuery = cb.or(predicates.toArray(new Predicate[0]));
nicoschl
  • 2,346
  • 1
  • 17
  • 17
  • 2
    Thanks, for the quick response, this solution works but with slight edit, i.e. new Predicate[length] where length is the No. Of elements that needs to fit in It was so close, great catch!! – Kalyan Pradhan Feb 17 '18 at 14:28
  • No problem. We use it everywhere in the code with a length of 0, but ok – nicoschl Feb 17 '18 at 14:40
  • 1
    The Change was a small one as follows Predicate finalQuery = cb.or(predicates.toArray(new Predicate[predicates.size()])); – Kalyan Pradhan Feb 17 '18 at 14:43
  • Ohh okay the 0 length might also be working, I will try that, but first time it gave me some exception might be due to some outofbounds exception, in java version 1.8.151 – Kalyan Pradhan Feb 17 '18 at 14:46
  • Thank you very much @nicoschi this saved my day, its a great and simple solution which I missed!! – Kalyan Pradhan Feb 17 '18 at 14:48
6

As an addition I would suggest using the following notation for newer Java versions:

builder.or(predicates.toArray(Predicate[]::new))
saschadoemer
  • 71
  • 1
  • 3
2

A sample code I wrote that might be helpful, here am gathering all predicates in a list and then converted list to array which is getting consumed by builder.

 public List< EntityClass> getData(List<Long> ids) {

    List<List<Long>> idPartitions = ListUtils.partition(ids, 999);
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<EntityClass> criteria = builder.createQuery(EntityClass.class);

    Root<EntityClass> root = criteria.from(EntityClass.class);

    List<Predicate> predicates = new ArrayList<>(idPartitions.size());
    for (List<Long> idPartition : idPartitions) {
      predicates.add(root.get("id").in(idPartition));
    }

    criteria.where(builder.and(predicates.toArray(new Predicate[0])));
    List<EntityClass> objects = entityManager.createQuery(criteria).getResultList();
    return objects;
  }
Dharman
  • 30,962
  • 25
  • 85
  • 135
NoisyBoy
  • 354
  • 3
  • 6