Comparer les entités de Date dans L'API critères

utilisant JPA 2 avec implémentation EclipseLink.

j'essaie de construire une requête dynamique qui devrait m'apporter quelques enregistrements persistés après une date donnée.

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() et le() sont les deux seules méthodes de l'API qui ressemblent peut m'aider dans ce cas. Cet avertissement est lancé par l'éclipse:

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>>

je peux imaginer que je ne prends pas le approche correcte pour ce problème, mais je ne peux trouver nulle part quelques conseils ou des conseils pour une solution possible.

35
demandé sur Community 2012-02-26 03:17:41

3 réponses

le problème est qu'avec L'API basée sur les chaînes de caractères, elle ne peut pas inférer le type pour la valeur de résultat de l'opération get . Ceci est expliqué par exemple dans Javadoc pour le chemin .

si vous utilisez

predicates.add(builder.lessThanOrEqualTo(root.<Date>get("dateCreated"), param));

au lieu de cela, il fonctionnera très bien, parce qu'il peut comprendre le type de retour de l'argument de type et découvrira qu'il est comparable. Notez que l'utilisation d'un paramétrer l'invocation de méthode root.<Date>get(...) (voir, par exemple, quand un appel de méthode paramétrisé est-il utile? ).

une autre solution (à mon avis meilleure) est d'utiliser l'API basée sur metamodel au lieu de l'API basée sur les chaînes de caractères. Un exemple simple sur le métamodèle canonique est donné par exemple ici . Si vous avez plus de temps à investir, il s'agit d'un bon article à propos de la statique metamodel: dynamique, Typesafe requêtes dans JPA 2.0

61
répondu Mikko Maunu 2017-05-23 11:54:56

vous devez utiliser le métamodèle généré pour accéder aux attributs est un moyen vraiment sûr. Si vous utilisez des chaînes de caractères pour faire référence à vos attributs, les types ne peuvent être déduits que du type générique explicite utilisé lors de l'appel de la méthode, ou par un type cast, ou par l'inférence de type automatique faite par le compilateur:

Path<Date> dateCreatedPath = root.get("dateCreated");
predicates.add(builder.lessThanOrEqualTo(dateCreatedPath, dateLimit));
15
répondu JB Nizet 2012-03-26 06:51:47

j'ai eu une erreur similaire mais avec la syntaxe predicates.add(cb.greaterThan(article.get(Article_.created), since)); et j'ai trouvé cette page. La cause pour moi, s'est avéré être que j'avais mis à jour mon projet de Java 1.7 à 1.8, et dans le processus avait configuré Maven pour compiler pour Java 1.8 aussi bien. J'ai simplement dû changer Maven compiles de nouveau à 1.7, tout en maintenant le reste du projet à 1.8, pour corriger l'erreur.

1
répondu Bjørn Stenfeldt 2017-01-20 07:34:54