Спецификация JPA Criteria нечувствительна к акценту на SingularAttribute
Я хочу сделать поиск без учета акцентов, я пытался реализовать решения, найденные по другим вопросам:
1) /questions/31343345/ignorirovat-v-postroitele-kriteriev-v-jpa/31343352#31343352
criteriaBuilder.lower(Person_.surname),
Expression<String> firstName = personRoot.get("firstName");
criteria.where(builder.and(
builder.equal(builder.upper(firstName ), filter.getFirstName())),
builder.equal(personRoot.get("lastName"), filter.getLastName()));
3) /questions/34776285/jpa2-nechuvstvitelen-k-registru-kak-i-vezde/34776308#34776308
builder.lower(
root.get(
type.getDeclaredSingularAttribute("username", String.class)
)
)
Я использую фильтрацию JHipser: https://github.com/TheDoctor-95/FuryViewer/wiki/JPA-Criteria-Queries-with-JHipster-(Filtering-your-entities) и спецификацию из Spring Data: https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/
У меня есть SingularAttribute<"My entity class", String> внутри метода buildSpecification:
Specifications<Festival> specification = Specifications.where(null);
specification = specification.or(buildStringSpecification(criteria.getNom(), Festival_.nom));
Поэтому я не могу использовать методы из предыдущего примера вопросов:
Когда я пытаюсь использовать решение 1:
specification = specification.or(buildSpecification(criteria.getNom(), cb.lower(Festival_.nom)));
Я получаю это исключение
The method lower(Expression<String>) in the type CriteriaBuilder is not applicable for the arguments (SingularAttribute<Festival,String>)
Несмотря на это, метод более низкого возвращает (Expression), и он не совпадает с тем, что хочет buildStringSpecification: buildStringSpecification (StringFilter, SingularAttribute) в типе QueryService не применяется для аргументов (StringFilter, Expression)
1 ответ
Хорошее решение - создать анонимную спецификацию и переопределить ее метод toPredicate следующим образом:
public <T> Specification<T> buildUnaccentLikeStringSpecification(StringFilter filter , SingularAttribute<T , String> field) {
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb)
{
return cb.like(
cb.function("unaccent" , String.class , cb.upper(root.get(field)))
, toWrapLikeQuery(stripAccents(filter.getContains())
)
);
}
};
}