I wrote two Specifications which return null if their parameter is null.
public static Specification<Prodotto> getProdottoByLineaSpec (String linea) {
if (linea != null) {
return (root, query, criteriaBuilder) -> {
return criteriaBuilder.like((root.join("linea")).get("nome"), "%"+linea+"%");
};
}
else return null;
}
public static Specification<Prodotto> getProdottoByIngSpec (String ing) {
if (ing != null) {
return (root, query, criteriaBuilder) -> {
return criteriaBuilder.like(((root.join("listaQuoteIng")).join("ing")).get("nome"), "%"+ing+"%");
};
}
else return null;
}
Then I created a third one that combines the previous ones with an and
operator inside a where
clause:
public static Specification<Prodotto> getProdottoByMainTraits (String linea, String ing) {
return Specification.where(getProdottoByLineaSpec(linea).and(getProdottoByIngSpec(ing)));
}
Now, that's the funny part:
ByLinea
returns null
, i get a nullPointerException
from checkPackageAccess
when resolving the where
clause.ByIng
returns null
, it just gets ignored (like it should be) and the query matches just the other predicate.ByIng
as the first one and then ByLinea
inside the where
clause, everything works in every combination.It is a good practice to avoid returning null
from methods.
You can use criteriaBuilder
.conjunction() to ignore null
parameter Specification
. It generates always true
Predicate
. There is an opposite method criteriaBuilder
.disjunction()
public static Specification<Prodotto> getProdottoByLineaSpec (String linea) {
return (root, query, criteriaBuilder) -> {
if (linea == null) {
return criteriaBuilder.conjunction();
}
return criteriaBuilder.like(
(root.join("linea")).get("nome"),
"%" + linea + "%"
);
}
}
P.S. You get NullPointerException
if first Specification
is null
trying to access a method and
.
To be clear it looks like this
Specification.where(null.and(getProdottoByIngSpec(ing)));
But if only second Specification
is null
this one works
Specification.where(getProdottoByLineaSpec(linea).and(null));
because and method parameter can be null