How to use Java CriteriaBuilder's notLike method when comparing tables?

24 Views Asked by At

I have two Entity's.

Recipe:

@jakarta.persistence.Entity 
public class Recipe implements Serializable {

private static final long serialVersionUID = 1L;

@jakarta.persistence.Id @jakarta.persistence.GeneratedValue
private Integer id;

private String name;

private String instructions;

private Boolean isVegetarian;

private String numberOfServings;

@jakarta.persistence.OneToMany(cascade = CascadeType.ALL)
@Valid
private List<@Valid Ingredient> includedIngredients = new ArrayList<>();

@jakarta.persistence.OneToMany(cascade = CascadeType.ALL)
@Valid
private List<@Valid Ingredient> excludedIngredients;

public Recipe() {
  super();
}

Ingredient:

@jakarta.persistence.Entity
public class Ingredient implements Serializable {

private static final long serialVersionUID = 1L;

@jakarta.persistence.Id @jakarta.persistence.GeneratedValue
private Integer id;

private String name;

private Boolean required;

public Ingredient() {
  super();
}

I've created a CriteriaBuilder to allow users to find recipes that only have certain ingredients. Eg. Find me all recipes that have "Garlic" and "Onions".

I have successfully done that:

List<Predicate> ingredientsPredicates = new ArrayList<>();

for (Ingredient ingredient : fields.getIncludedIngredients()) {
    ingredientsPredicates.add(builder.like(builder.lower(recipe.get("includedIngredients").<String> get("name")), "%" + ingredient.getName().toLowerCase() + "%"));
}

allPredicates.add(builder.or(ingredientsPredicates.toArray(new Predicate[]{})));

However, I also need to allow the user to find recipes that do NOT contain certain ingredients. Eg. Find me all recipes that don't have "Garlic" and "Onions".

I thought something similar would work, but no such luck....I was able to successfully use the 'notLike' method for the Recipe name, but not for the includedIngredients. Any ideas? I tried this:

List<Predicate> ingredientsPredicates = new ArrayList<>();

for (Ingredient ingredient : fields.getExcludedIngredients()) {
    ingredientsPredicates.add(builder.notLike(builder.lower(recipe.get("includedIngredients").<String> get("name")), "%" + ingredient.getName().toLowerCase() + "%"));
}

allPredicates.add(builder.or(ingredientsPredicates.toArray(new Predicate[]{})));
0

There are 0 best solutions below