Tengo una consulta que escribiría en una versión anterior de Hibernate (utilizando el bean SessionFactory). Sin embargo, cambié a Spring Boot y ahora estoy utilizando JPA 2, que esencialmente parece una capa de abstracción sobre Hibernate. ¿Alguien podría orientarme sobre cómo agregar restricciones? Creo que ahora tendré que usar el bean EntityManager con JPA. Aquí está la consulta anterior.

@Override
@SuppressWarnings("unchecked")
public List<Party> queryPartiesBetweenDates(Date startDate, Date endDate, String sortBy, Integer count) {
    Criteria criteria = getCurrentSession().createCriteria(Party.class);
    if (startDate != null) {
        criteria.add(Restrictions.ge("startDate", startDate));
    }
    if (endDate != null) {
        criteria.add(Restrictions.lt("endDate", endDate));
    }
    if (count != null) {
        criteria.setMaxResults(count);
    }
    if (sortBy == null || !sortBy.equals("distance")) {
        criteria.addOrder(Order.asc("startDate"));
    }
    return criteria.list();
}

¡Gracias!

1
tsaebeht 16 ene. 2017 a las 14:31
1
 – 
Jobin
16 ene. 2017 a las 14:47

1 respuesta

La mejor respuesta

CriteriaBuilder es un poco más detallado que la API de restricción de hibernación nativa, la razón principal es que está completamente escrito cuando usa el MetaModel, lo que significa que el código no se compilará si el tipo o nombre de una columna que causa una consulta inválido. Aquí hay un ejemplo que no usa las clases MetaModel generadas, y en su mayoría se parece al código antiguo de Hibernate.

EntityManager em = emf.createEntityManager(); // or injected

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Party> query = cb.createQuery(Party.class);
Root<Party> partyRoot = query.from(Party.class);
query.select(partyRoot);

Predicate predicate = null;
Path<Date> startDatePath = partyRoot.<Date>get("startDate");
if (startDate != null) {
    predicate = cb.greaterThanOrEqualTo(startDatePath, startDate);
}
if (endDate != null) {
    Predicate additionalPredicate = cb.lessThanOrEqualTo(partyRoot.<Date>get("endDate"), startDate);
    if (predicate == null) {
        predicate = additionalPredicate;
    } else {
        predicate = cb.and(predicate, additionalPredicate);
    }
}
query.where(predicate);

if (sortBy == null || !sortBy.equals("distance")) {
    query.orderBy(cb.asc(startDatePath));
}

return em.createQuery(query).setMaxResults(count).getResultList();

Si tiene muchos predicados, puede ser una buena idea agregarlos a una lista o crear un método de utilidad para manejarlos.

1
Klaus Groenbaek 16 ene. 2017 a las 20:26
Me gustó cómo evitaste el uso de clases metamodales. ¿Se pueden escribir casi todas las consultas sin las clases metamodales de esta manera?
 – 
tsaebeht
17 ene. 2017 a las 11:51
1
No necesita el metamodelo estático, siempre que sepa el nombre del campo. Algunas veces tendrás que emitir el resultado de Root.get (), porque Path y Expression son muy generales, y es posible que debas saber que el campo hace referencia a un elemento de colección para poder usarlo. para la sintaxis de unión. Sin embargo, la mejor opción es generar el metamodelo (estático) como parte de la construcción (procesamiento de anotaciones), esto generará una clase llamada Party_, por lo que puede usar Party_.startDate para obtener la ruta, y luego es completamente seguro.
 – 
Klaus Groenbaek
17 ene. 2017 a las 15:07