比较JPA Criteria API中的Date实体

Ion*_*nut 45 java date criteria-api jpa-2.0

将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));
}
Run Code Online (Sandbox Code Playgroud)

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>>
Run Code Online (Sandbox Code Playgroud)

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

Mik*_*unu 75

问题是,使用基于字符串的API,它无法推断get-Operation 结果值的类型.例如,在Javadoc for Path中对此进行了解释.

如果你使用

predicates.add(builder.lessThanOrEqualTo(root.<Date>get("dateCreated"), param));
Run Code Online (Sandbox Code Playgroud)

相反,它会正常工作,因为它可以从类型参数中找出返回类型,并会发现它具有可比性.注意,使用参数化方法调用root.<Date>get(...)(参见,例如, 何时参数化方法调用有用?).

另一个(在我看来更好)解决方案是使用基于元模型的API而不是基于字符串的API.这里给出了一个关于规范元模型的简单示例.如果您有更多时间投资,这是一篇关于静态元模型的好文章:JPA 2.0中的动态,类型安全查询

  • 不是一个糟糕的导入问题,它是一个错误,一个非常古老的错误。要解决此问题,您必须将其声明为变量并将其用作参数:`Path path = root.get( .....); builder.greaterThan(路径,日期);` (2认同)

JB *_*zet 16

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

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