code: private <R,T> Predicate createPredicateFromIntersectingCriteriaList(CriteriaQuery<R> query, CriteriaBuilder builder, Class<T> queryType, List<QueryCriteria> intersectingCriteriaList, QueryWhere queryWhere  ) {
          combineIntersectingRangeCriteria(intersectingCriteriaList);
          assert intersectingCriteriaList.size() > 0 : "Empty list of currently intersecting criteria!";
          Predicate [] intersectingPredicates = new Predicate[intersectingCriteriaList.size()];
          int i = 0;
          for( QueryCriteria intersectingCriteria : intersectingCriteriaList ) {
              Predicate predicate = createPredicateFromSingleOrGroupCriteria(query, builder, queryType, intersectingCriteria, queryWhere );
              assert predicate != null : "Null predicate when evaluating individual intersecting criteria [" + intersectingCriteria.toString() + "]";
              intersectingPredicates[i++] = predicate;
          }
  
          Predicate predicate;
          if( intersectingPredicates.length > 1 ) {
              predicate = builder.and(intersectingPredicates);
          } else {
             predicate = intersectingPredicates[0];
          }
  
          return predicate;
      }
docs: This method is necessary because the AND operator in SQL has precedence over the OR operator.
  </p>
  That means that intersecting criteria should always be grouped together (and processed first, basically), which is essentially
  what this method does.
  
  @param query The {@link CriteriaQuery} that is being built
  @param intersectingCriteriaList The list of intersecting (ANDed) {@link QueryCriteria}
  @param builder The {@link CriteriaBuilder} builder instance
  @param queryType The (persistent {@link Entity}) {@link Class} that we are querying on
  @return A {@link Predicate} created on the basis of the given {@link List} of {@link QueryCriteria}