El siguiente ejemplo de JPA crea una selección de datos estándar, que retorna una serie de columnas para una query determinada.
1. Se crea la query y el FROM sobre el PO principal de la misma. La claúsula es sobre el PO, pero la query retornará una lista de DTOs. El PO esta mapeado directamente al modelo en BBDD, mientras que el DTO es una representación con tipos primitivos y clases ‘wrapper’, del mismo.
/* Criteria builder */
CriteriaBuilder criteria = getEntityManager().getCriteriaBuilder();
CriteriaQuery<DonutDTO> query = criteria.createQuery(DonutDTO.class);
Root<DonutPO> root = query.from(DonutPO.class);
2. Se añaden los predicados de la claúsula WHERE. Aquí, ‘cream’ es un atributo de DonutPO, mientras que ‘toppingPO’ es asimismo un atributo de esta clase que representa una relación 1 a n, siendo ‘id’ el atributo PK de su clase PO.
Predicate conditions = criteria.or(
criteria.equal(root.get("toppingPO").get("id"), topping),
criteria.equal(root.get("cream"), cream));
query.where(conditions);
3. Se establecen los campos que se devolverán en la query. Se pueden solicitar campos del PO principal (DonutPO) o de aquellos que estén relacionados mediante su PO correspondiente (ToppingPO). Para ello, el DTO de destino ha de tener un constructor con los campo en el mismo orden en el que se establecen aquí. En este caso, debe existir un constructor con 2 campos, uno para “name” y otro para “flavour”.
List<Selection> listFields = new ArrayList<Selection>();
Path<?> id = root.get("name");
listFields.add(id);
Join<?, ?> joinTopping = root.join("toppingPO", JoinType.LEFT);
Path<?> toppingName = joinTopping.get("flavour");
criteria.multiselect(listFields.toArray(new Selection[0]));
4. Se ejecuta la query.
/* Execute query */
List<DonutPO> donutList = getEntityManager().createQuery(query).getResultList();