Спецификация JPA Criteria нечувствительна к акценту на SingularAttribute

Я хочу сделать поиск без учета акцентов, я пытался реализовать решения, найденные по другим вопросам:

1) /questions/31343345/ignorirovat-v-postroitele-kriteriev-v-jpa/31343352#31343352

 criteriaBuilder.lower(Person_.surname), 

2) /questions/32556276/uslovie-nechuvstvitelnogo-k-registru-api-jpa-2-bez-ispolzovaniya-metamodeli/32556282#32556282

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())
                    )                       
                    );
        }
    };
}
Другие вопросы по тегам