2012-02-25 22 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で唯一の2つの方法です。この警告はいえ日食によってスローされます。

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?を参照)。

もう1つ(私の意見では良い)ソリューションは、文字列ベースのAPIの代わりにメタモデルベースのAPIを使用することです。標準的なメタモデルについての簡単な例は、例えばhereです。投資する時間があれば、これは静的メタモデルに関する良い記事です:Dynamic, typesafe queries in JPA 2.0

+1

NetBeans 8.2は、依然として基準で警告します。どうしてか分かりません。 @bukwon: 'javax.persistence()'をインポートしてください。 'builder.greaterThanOrEqualsTo(root.get(Some_date)、date)' <> 'builder.greaterThanOrEqualsTo(ルート。 get(Some_date)、date)' –

+0

@ .criteria.Predicate'ではなく、 'java.util.function.Predicate'です。それは私のためにそれを修正:) – Hank

+0

悪いインポートの問題ではない、それはバグ、非常に古いものです。 回避策としては、変数として宣言し、パラメータとして使用する必要があります。 'Path path = root.get(.....); builder.greaterThan(パス、日付); ' – FiruzzZ

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にアップグレードしたことが判明し、このプロセスでJava 1.8用にもMavenをコンパイルするように設定しました。エラーを修正するために、プロジェクトの残りの部分を1.8に保ちながら、Mavenコンパイルを1.7に戻すだけでした。