Category Archives: JPA

Selección de datos en JPA II

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();

Selección de datos en JPA I

A continuación se presenta un sencillo ejemplo de como implementar una selección en JPA usando la clase CriteriaBuilder. Esto tiene la ventaja de que podemos implementar una selección de datos en Java sin teclear ni una sola query, ni en SQL ni en ningún otro lenguaje de consulta, haciedola totalmente independiente de la capa de datos y omitiendo la necesidad de almacenar y mantener dichas queries.

1. Se crea el objeto ‘query’ y la representación de la clausula FROM sobre el elemento del modelo de datos principal de nuestra claúsula.

CriteriaBuilder cb = this.getEntityManager().getCriteriaBuilder();
CriteriaQuery<Long> countTransaction = cb.createQuery(Long.class);
Root<BosTransactionsPO> root = countTransaction.from(BosTransactionsPO.class);

2. Se establecen los predicados de la clausula WHERE.

/* Predicates */
List<Predicate> predicates = new ArrayList<Predicate>();
Long plazaId = itineraryArg.getTollPlazaId();
if (plazaId != null) {
Predicate p = cb.equal(root.get("tollPlazaPO").get("id"), plazaId);
predicates.add(p);
}
countTransaction.where(predicates.toArray(new Predicate[0]));

3. Se establecen lo que se retornará en la selección. En este caso, es un SELECT COUNT(*).

countTransaction.select(cb.count(root));

4. Se ejecuta la query.

/* Execute query */
Long count = getEntityManager().createQuery(countTransaction).getSingleResult();