With Criteria Builder / Criteria Query is it possible to use the selected fields in the where statement?
My end goal is to be able to let the UI apply filters to the DTO and I'm thinking the easiest way would be to be apply those filters on the selected fields.
So if for example, my query returned a DTO with firstName
(user table), lastName
(user table), and bookmarked
(sub query across another table), could I perform my default query and then apply another where clause looking at the firstName, lastName and bookmarked?
something like
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
I have all the query working except I'm not sure how to filter the results based on the selected fields.
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();
I know I could add cq.where(cb.equal(root.get("firstName"), "Jane"));
but that's not very dynamic and I can't figure out a way to add a where on the bookmarked part, something like cq.where(cb.equal(root.get("firstName"), "Jane"), cb.equal(subquery.getSelection().isNotNull(), true) );
doesn't work, because the subquery isn't executed there.