JPA-запрос, в котором приводится оператор для выбранных полей - PullRequest
3 голосов
/ 12 февраля 2020

С помощью Criteria Builder / Criteria Query можно использовать выбранные поля в операторе where?

Моя конечная цель - позволить интерфейсу применять фильтры к DTO, и я думаю, что самый простой способ - применить эти фильтры к выбранным полям.

Так что, если, например, мой запрос вернул DTO с firstName (таблица пользователя), lastName (таблица пользователя) и bookmarked (подзапрос в другой таблице), я мог бы выполнить свой заданный по умолчанию запрос, а затем применить другое предложение, где, глядя на firstName, lastName и в закладки?

что-то вроде

select 
   u.firstName as first,
   u.lastName as last, 
   (select CAST(1 AS BIT) from user_bookmark b where b.user_id=u.id as bookmarked)
from user u
where first = 'john' and bookmarked = true; //Dynamic part from UI 

У меня работает весь запрос, кроме я не уверен, как отфильтровать результаты на основе выбранных полей.

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<OfficerDTO> cq = cb.createQuery(OfficerDTO.class);
    Root<OfficerEntity> root = cq.from(OfficerEntity.class);

    Subquery<Long> subquery = null;
    subquery = cq.subquery(Long.class);

    Root<OfficerBookmarkEntity> subRoot = subquery.from(OfficerBookmarkEntity.class);

    System.out.println("************ adding query");
    subquery.select(subRoot.get("user").get("id"));
    List<Predicate> predicates = new ArrayList<>();

    predicates.add(cb.equal(subRoot.get("officer").get("id"), root.get("id")));
    predicates.add(cb.equal(subRoot.get("user").get("id"), 123456789L));
    subquery.where(cb.and(predicates.toArray(new Predicate[]{})));

    cq.multiselect(
                root.get("firstName").alias("firstName"),
                root.get("lastName").alias("lastName"),
                subquery.getSelection().isNotNull().alias("bookmarked")
    );


    TypedQuery<OfficerDTO> q = em.createQuery(cq);
    return q.getResultList();

Я знаю, что могу добавить cq.where(cb.equal(root.get("firstName"), "Jane"));, но это не очень динамично c, и я не могу придумать, как добавить точку в закладке, что-то вроде cq.where(cb.equal(root.get("firstName"), "Jane"), cb.equal(subquery.getSelection().isNotNull(), true) ); не делает не работает, потому что подзапрос там не выполняется.

...