Спецификация JPA не влияет на метод CriteriaBuilder.or () - PullRequest
0 голосов
/ 05 апреля 2020

То, что я хочу получить, похоже на -

SELECT * FROM emials WHERE user_id = ?1 AND (`to` like '%?2%' OR `from` LIKE '%?2%' OR subject LIKE '%?2%');

Чтобы получить такое, у меня есть следующая спецификация, например -

public class VendorEmailSpecification {
    public static Specification<VendorEmail> filter(String filterText) {
        return new Specification<VendorEmail>() {
            @Override
            public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.conjunction();

                if(!StringUtils.isEmpty(filterText)) {
                    /***
                    * this block donot have any effects
                    **/
                    predicate = criteriaBuilder.or(
                            criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("to"),"%"+ filterText +"%")),
                            criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("from"),"%"+ filterText +"%")),
                            criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("subject"),"%"+ filterText +"%")),
                            criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("message"),"%"+ filterText +"%"))
                   );
                }
                // there is an relation of ManyToOne with user and AuthUserThread.getContext() gives an object of User entity.
                // this working perfectly
                predicate = criteriaBuilder.and(predicate,criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext()));


                return predicate;
            }
        };
    }
}

Какая ошибка и как я могу это исправить?

Ответы [ 2 ]

0 голосов
/ 05 апреля 2020

Я решаю эту проблему по-другому -

public class VendorEmailSpecification {
    public static Specification<VendorEmail> filter(String filterText) {
        return new Specification<VendorEmail>() {
            @Override
            public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.conjunction();
                predicate = criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext());
                if(!StringUtils.isEmpty(filterText)) {
                    Predicate toPredicate = criteriaBuilder.like(root.get("to"), "%"+filterText+"%");
                    Predicate fromPredicate = criteriaBuilder.like(root.get("from"), "%"+filterText+"%");
                    Predicate subjectPredicate = criteriaBuilder.like(root.get("subject"), "%"+filterText+"%");
                    Predicate messagePredicate = criteriaBuilder.like(root.get("message"), "%"+filterText+"%");
                    Predicate orPredicate = criteriaBuilder.or(toPredicate, fromPredicate, subjectPredicate, messagePredicate);
                    predicate = criteriaBuilder.and(predicate, orPredicate);
                    return predicate;
                }

                predicate = criteriaBuilder.and(predicate);
                return predicate;
            }
        };
    }
}
0 голосов
/ 05 апреля 2020

Похоже, что параметр filterText выйдет из области видимости при вызове метода toPredicate().

Если вы добавите элемент в анонимный экземпляр Specification<VendorEmail>, возвращаемый filter() метод, присвойте элементу значение параметра filterText и обновите оставшийся код для ссылки на новый член, как показано ниже, который должен решить проблему:

public class VendorEmailSpecification {
    public static Specification<VendorEmail> filter(String filterText) {
        return new Specification<VendorEmail>() {
            private String filterValue = filterText;

            @Override
            public Predicate toPredicate(Root<VendorEmail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.conjunction();
                if(!StringUtils.isEmpty(this.filterValue)) {
                    /***
                    * this block donot have any effects
                    **/
                    predicate = criteriaBuilder.or(
                        criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("to"),"%"+ this.filterValue +"%")),
                        criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("from"),"%"+ this.filterValue +"%")),
                        criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("subject"),"%"+ this.filterValue +"%")),
                        criteriaBuilder.or(predicate, criteriaBuilder.like(root.get("message"),"%"+ this.filterValue +"%"))
               );
            }
            // there is an relation of ManyToOne with user and AuthUserThread.getContext() gives an object of User entity.
            // this working perfectly
            predicate = criteriaBuilder.and(predicate,criteriaBuilder.equal(root.get("user"), AuthUserThread.getContext()));
            return predicate;
            }
        };
    }
}
...