java - query - Comparar entidades de fecha en API de criterios JPA
jpql date comparison (3)
Usando JPA 2 con la implementación de EclipseLink.
Intento crear una consulta dinámica que me lleve algunos registros persistentes después de una fecha determinada.
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Event> criteria = builder.createQuery(Event.class);
Root<Event> root = criteria.from(Event.class);
criteria.select(root);
criteria.distinct(true);
List<Predicate> predicates = new ArrayList<Predicate>();
//...
if (dateLimit != null){
ParameterExpression<Date> param = builder.parameter(Date.class, "dateLimit");
predicates.add(builder.lessThanOrEqualTo(root.get("dateCreated"), param));
}
lessThanOrEqualTo()
y le()
son los únicos dos métodos en la API que parecen me pueden ayudar en este caso. Esta advertencia es lanzada por el eclipse sin embargo:
Bound mismatch: The generic method lessThanOrEqualTo(Expression<? extends Y>, Expression<? extends Y>)
of type CriteriaBuilder is not applicable for the arguments (Path<Object>, ParameterExpression<Date>).
The inferred type Object is not a valid substitute for the bounded parameter
<Y extends Comparable<? super Y>>
Me puedo imaginar que no estoy tomando el enfoque correcto para este problema, pero no puedo encontrar en ningún lado algunos consejos o sugerencias para una posible solución.
El problema es que con la API basada en cadenas no puede inferir el tipo para el valor de resultado de la operación get
. Esto se explica, por ejemplo, en Javadoc para Path .
Si utiliza
predicates.add(builder.lessThanOrEqualTo(root.<Date>get("dateCreated"), param));
en su lugar, funcionará bien, porque puede deducir el tipo de devolución del argumento de tipo y descubrirá que es comparable. Tenga en cuenta el uso de un método parametrizado de invocación de root.<Date>get(...)
(consulte, por ejemplo, ¿ Cuándo es útil una llamada de método parametrizada? ).
Otra solución (en mi opinión mejor) es utilizar la API basada en metamodelo en lugar de la basada en cadenas. Un ejemplo simple sobre metamodelo canónico se da, por ejemplo, here . Si tiene más tiempo para invertir, este es un buen artículo sobre el metamodelo estático: consultas dinámicas y seguras en JPA 2.0
Necesita usar el metamodelo generado para acceder a los atributos de una manera realmente segura. Si usa cadenas para hacer referencia a sus atributos, los tipos solo se pueden deducir del tipo genérico explícito utilizado al llamar al método, o mediante un tipo de conversión, o mediante la inferencia de tipo automática realizada por el compilador:
Path<Date> dateCreatedPath = root.get("dateCreated");
predicates.add(builder.lessThanOrEqualTo(dateCreatedPath, dateLimit));
predicates.add(cb.greaterThan(article.get(Article_.created), since));
un error similar pero con la sintaxis predicates.add(cb.greaterThan(article.get(Article_.created), since));
y encontré esta página. La causa para mí, resultó ser que había actualizado mi proyecto de Java 1.7 a 1.8, y en el proceso también había configurado Maven para compilar para Java 1.8. Simplemente tuve que cambiar las compilaciones de Maven a 1.7, mientras mantenía el resto del proyecto en 1.8, para arreglar el error.