I want to use Hibernate's CriteriaBuilder between method which is defined as:
<Y extends Comparable<? super Y>> Predicate between(Expression<? extends Y> v, Y x, Y y)
I have the following abstract class, the important method is toPredicate
.
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
abstract public class RangeObject<T> {
protected T from;
protected T to;
public RangeObject(T from, T to) {
this.from = from;
this.to = to;
}
public T getFrom() {
return from;
}
public T getTo() {
return to;
}
/**
* Create a predicate for testing whether the second argument is
* between the `from` and `to` values
*
* @param builder Criteria Builder instance
* @param path Attribute path from a bound type
* @return between predicate
*/
public Predicate toPredicate(
CriteriaBuilder builder,
Path<T> path
) {
if (isSingleValue(from, to)) {
return builder.equal(path, from);
} else {
return builder.between(path, from, to);
}
}
/**
* @param from From value
* @param to To value
* @return Whether parameters to this method match
*/
abstract public boolean isSingleValue(T from, T to);
}
It has a parameter Path<T>
.
Path interface is defined as interface Path<X> extends Expression<X>
which as far as I understand should be compatible with Expression<? extends Y>
.
I get the following error:
no suitable method found for between(javax.persistence.criteria.Path<T>,T,T)
I even tried changing the toPredicate
method to:
public Predicate toPredicate(
CriteriaBuilder builder,
Expression<? extends T> expression
) {
if (isSingleValue(from, to)) {
return builder.equal(expression, from);
} else {
return builder.between(expression, from, to);
}
}
And I still get the same error:
no suitable method found for between(javax.persistence.criteria.Expression<capture#1 of ? extends T>,T,T)
If I hardcode the type, it works ( this is an example of what works: )
import ...
abstract public class RangeObject {
protected LocalDateTime from;
protected LocalDateTime to;
...
public Predicate toPredicate(
CriteriaBuilder builder,
Path<LocalDateTime> path
) {
if (isSingleValue(from, to)) {
return builder.equal(path, from);
} else {
return builder.between(path, from, to);
}
}
...
}
What am I doing wrong?
Based on method specification, arguments in between
method should extends Comparable
<Y extends Comparable<? super Y>> Predicate between(Expression<? extends Y> v, Y x, Y y);
If you make T
in your class specification extends Comparable
it would works for Path and Expression both.
public abstract class RangeObject<T extends Comparable<T>> {
protected T from;
protected T to;
.......
}