CriteriaBuilder.and & CriteriaBuilder.or, how-to?

criteria-api, jpa-2.0

Solution

Here's the where clause of your JPQL query:

where d.parent is null 
and (
    d.name like :term 
    or c.name like :term
    ) 

The where clause contains two predicates:

d.parent is null 

and

(d.name like :term 
 or c.name like :term)

The second predicate is an `or` containing two predicates:

d.name like :term

and

c.name like :term

So you need the same structure in your criteria query:

Predicate orClause = 
    cb.or(cb.like(root.<String>get("name"), param),
          cb.like(children.<String>get("name"), param));

c.where(cb.isNull(root.get("parent")),
        orClause);

Problem

I'm trying to change the following HQL to use JPA Criteria: ``` select distinct d from Department d left join fetch d.children c where d.parent is null and ( d.name like :term or c.name like :term ) order by d.name ``` `Department` has a `Set<Department>` of children. Criteria: ``` CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); CriteriaQuery<Department> c = cb.createQuery(Department.class); Root<Department> root = c.from(Department.class); root.fetch("children", JoinType.LEFT); Path<Department> children = root.join("children", JoinType.LEFT); c.orderBy(cb.asc(root.get("name"))); c.distinct(true); c.where(cb.isNull(root.get("parent"))); String param = "%" + "term" + "%"; cb.and(cb.like(root.<String> get("name"), param)); cb.or(cb.like(children.<String> get("name"), param)); TypedQuery<Department> tq = getEntityManager().createQuery(c); departments = tq.getResultList(); ``` I know it can be a bit terse, however, the HQL returns 24 and Criteria version 28. I think I'm not handling: ``` and (x = y OR z = y) ``` correctly. Any pointers will be greatly appreciated. Thanks.

Original source