Независимо от регистра isMember в l oop - API критерий JPA - PullRequest
0 голосов
/ 10 февраля 2020

Я создал следующий предикат, который соответствует заданному набору строк, например «a, b, c», против столбца, содержащего @ElementCollection Set<String>. Я хочу, чтобы все записи, которые содержат «а» или «б» или «c». Например, все эти записи / набор совпадений:

  • a // из-за
  • b,d // из-за b
  • c,f,g // из-за c

У меня есть предикат, который работает - мне нужно только сделать его нечувствительным к регистру (не хочу изменять базу данных):

private Predicate matchStringSet(Set<String> set, SetAttribute<DeliveryModeEntity, String> attribute,
        CriteriaBuilder criteriaBuilder, Root<DeliveryModeEntity> deliveryMode) {
        List<Predicate> matchEach = new ArrayList<>();
        for (String string : set) {
            matchEach.add(criteriaBuilder.isMember(string.toLowerCase(), deliveryMode.get(attribute)));

        }
        return criteriaBuilder.or(matchEach.toArray(new Predicate[] {}));

}

Как заставить deliveryMode.get(attribute) использовать строчные буквы или как сделать этот регистр нечувствительным. Я попытался использовать соединение, как упомянуто здесь: { ссылка }, но это не работает в течение для l oop - это создаст объединение для каждой строки в наборе.

1 Ответ

1 голос
/ 07 марта 2020

У меня есть похожая сущность, 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));
  }
}
...