import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import com.mysema.query.BooleanBuilder; import com.mysema.query.types.Expression; import com.mysema.query.types.Order; import com.mysema.query.types.Predicate; import com.mysema.query.types.expr.ComparableExpression; import com.mysema.query.types.expr.NumberExpression; public class QueryHelper { /** * Implementing pagination with seek method * http://use-the-index-luke.com/no-offset */ public static PredicateDecorator getSeekPredicate(List>> fields, List> values) { // where f1 < a // or (f1 = a and f2 < b) // or (f1 = a and f2 = b and f3 < c) return predicate -> { List expressions = new ArrayList<>(); for (int i = 0; i < fields.size(); i++) { Expression left = fields.get(i).getValue(); Comparable right = values.get(i); BooleanBuilder condition = new BooleanBuilder( fields.get(i).getKey() == Order.DESC ? lt(left, right) : gt(left, right)); for (int j = 0; j < fields.size(); j++) { Expression field = fields.get(j).getValue(); Comparable value = values.get(j); if (j < i) { condition.and(eq(field, value)); } else { expressions.add(condition); break; } } } predicate.andAnyOf(expressions.toArray(new Predicate[0])); }; } @SuppressWarnings({ "unchecked" }) private static , A extends Number & Comparable> Predicate lt(Expression left, Comparable right) { if (left instanceof ComparableExpression) { return ((ComparableExpression) left).lt((T) right); } if (left instanceof NumberExpression) { return ((NumberExpression) left).lt((A) right); } throw new IllegalArgumentException(String.valueOf(left)); } @SuppressWarnings({ "unchecked" }) private static , A extends Number & Comparable> Predicate gt(Expression left, Comparable right) { if (left instanceof ComparableExpression) { return ((ComparableExpression) left).gt((T) right); } if (left instanceof NumberExpression) { return ((NumberExpression) left).gt((A) right); } throw new IllegalArgumentException(String.valueOf(left)); } @SuppressWarnings({ "unchecked" }) private static , A extends Number & Comparable> Predicate eq(Expression left, Comparable right) { if (left instanceof ComparableExpression) { return ((ComparableExpression) left).eq((T) right); } if (left instanceof NumberExpression) { return ((NumberExpression) left).eq((A) right); } throw new IllegalArgumentException(String.valueOf(left)); } }