2012-02-25 71 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,以修復錯誤。