У меня есть похожая сущность, Widget
, имеющая теги:
@ElementCollection
@Column(name = "tag")
private List<String> tags = new ArrayList<>();
С тем, что у вас есть, чтобы найти все виджеты с данными тегами, используйте:
private Predicate matchTags(List<String> tags, Root<Widget> root, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<>();
for (String tag : tags) {
predicates.add(cb.isMember(tag, root.get(Widget_.tags)));
}
return PredicateReducer.OR.reduce(cb, predicates); // cb.or(predicates.toArray(new Predicate[0]));
}
Чтобы найти все виджеты, имеющие теги без учета регистра, сначала объединяют теги, а затем выполняют аналогичный поиск:
private Predicate matchTagsCaseInsensitive(List<String> tags, Root<Widget> root, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<>();
Join<Widget, String> joinedTag = root.join(Widget_.tags);
for (String tag : tags) {
predicates.add(cb.like(cb.lower(joinedTag), tag.toLowerCase()));
}
return PredicateReducer.OR.reduce(cb, predicates); // cb.or(predicates.toArray(new Predicate[0]));
}
Редактировать: добавление PredicateReducer
Я нахожу Я сам AND
-ing или OR
-ing-предикаты часто, поэтому эти операции заключены в перечисление:
public enum PredicateReducer {
AND {
@Override
public Predicate reduce(CriteriaBuilder cb, List<Predicate> predicates) {
return cb.and(predicates.toArray(new Predicate[0]));
}
},
OR {
@Override
public Predicate reduce(CriteriaBuilder cb, List<Predicate> predicates) {
return cb.or(predicates.toArray(new Predicate[0]));
}
};
public abstract Predicate reduce(CriteriaBuilder cb, List<Predicate> predicates);
public Predicate reduce(CriteriaBuilder cb, Predicate... predicates) {
return reduce(cb, Arrays.asList(predicates));
}
}