2012-02-25 74 views
34

使用JPA 2与EclipseLink实现。比较日期实体在JPA标准API

我试图建立一个动态查询,应该给我一些记录在给定的日期后保留。

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中仅有的两个方法看起来像可以帮助我在这种情况下。这个警告是由Eclipse虽然抛出:

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

我可以想像,我不会考虑这个问题的正确方法,但我找不到任何地方的可能解决方案的一些提示或指针。

回答

58

问题是,对于基于字符串的API,它不能推断出get运行结果值的类型。这例如在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

NetBeans 8.2仍会以条件警告。我不知道为什么。 ''builder.greaterThanOrEqualsTo(root.get(Some_.date),date)''''builder.greaterThanOrEqualsTo(root。 get(Some_.date),date)' – 2016-10-04 11:06:56

+0

@Jin Kwon:确保导入'javax.persistence .criteria.Predicate',而不是'java.util.function.Predicate'。这为我修复:) – Hank 2017-03-07 14:57:54

+0

是不是一个不好的进口问题,这是一个错误,一个非常古老的问题。 解决方法您必须将其声明为变量并将其用作参数: 'Path path = root.get(.....); builder.greaterThan(路径,日期);' – FiruzzZ 2017-11-14 12:03:36

12

您需要使用生成的元模型访问属性是一种非常安全的方法。

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

:如果您使用字符串来引用您的属性,类型只能从打电话时的方法,或者通过类型转换,或由编译器完成的自动类型推断使用显式泛型类型推断我收到了类似的错误,但语法为predicates.add(cb.greaterThan(article.get(Article_.created), since));,并且找到了此页面。原因对我来说,原来是我将项目从Java 1.7升级到1.8,并且在此过程中也配置了Maven以便为Java 1.8进行编译。我只需将Maven编译回1.7,同时保持项目的其余部分为1.8,以修复错误。