比较JPA Criteria API中的Date实体

时间:2012-02-25 23:17:42

标签: java date jpa-2.0 criteria-api

将JPA 2与EclipseLink实现结合使用。

我正在尝试构建一个动态查询,它应该会在给定日期之后保留一些记录。

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()le()是API中仅有的两种方法,在这种情况下可能对我有帮助。这个警告是由日食引发的:

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

我可以想象我没有采取正确的方法解决这个问题,但我找不到任何可能解决方案的提示或指示。

4 个答案:

答案 0 :(得分:68)

问题在于,使用基于字符串的API,它无法推断get - Operation的结果值的类型。例如,在Javadoc for Path中解释了这一点。

如果您使用

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

相反,它会正常工作,因为它可以从类型参数中找出返回类型,并会发现它是可比较的。注意,使用参数化方法调用root.<Date>get(...)(参见,例如,When is a parameterized method call useful?)。

另一个(在我看来更好)解决方案是使用基于元模型的API而不是基于字符串的API。有关规范元模型的简单示例,例如here。如果您有更多时间投资,这是一篇关于静态元模型的好文章:Dynamic, typesafe queries in JPA 2.0

答案 1 :(得分:15)

您需要使用生成的元模型来访问属性是一种非常安全的方式。如果使用字符串来引用属性,则只能从调用方法时使用的显式泛型类型或类型转换或编译器自动类型推断推断类型:

Path<Date> dateCreatedPath = root.get("dateCreated");
predicates.add(builder.lessThanOrEqualTo(dateCreatedPath, dateLimit));

答案 2 :(得分:2)

我收到了类似的错误,但语法为predicates.add(cb.greaterThan(article.get(Article_.created), since));并找到了此页面。我的原因,原来是我已经将我的项目从Java 1.7升级到1.8,并且在此过程中还配置了Maven以便为Java 1.8编译。我只需要将Maven编译更改回1.7,同时将项目的其余部分保持为1.8,以修复错误。

答案 3 :(得分:0)

当我处理谓词时,我遇到了同样的问题。除Date类型外,它适用于所有类型。我尝试了所有方法,最简单的方法是:

predicates.add(builder.greaterThanOrEqualTo(root.get(criteria.getKey()), (Date)criteria.getValue()));

我在(Date)之前添加了criteria.getValue(),这有助于将我的值Object识别为Date类型。