2011-07-04 25 views
8

私が動作するように、次のNamedQueryを取得しようとしている:Hibernate:OFFSETとLIMITに名前付きパラメータを使用できませんか?

@NamedQuery(name="MyEntity.findByUser", query="SELECT m FROM MyEntity m WHERE m.owner = :user OFFSET :offset LIMIT :limit") 

問題は、これはサーバーの起動時に次のスタックトレースと爆発する休止状態を引き起こすことがある。いくつか試した後

[INFO] [talledLocalContainer] java.lang.NullPointerException 
[INFO] [talledLocalContainer] at org.hibernate.hql.ast.ParameterTranslationsImpl.getNamedParameterExpectedType(ParameterTranslationsImpl.java:63) 
[INFO] [talledLocalContainer] at org.hibernate.engine.query.HQLQueryPlan.buildParameterMetadata(HQLQueryPlan.java:296) 
[INFO] [talledLocalContainer] at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:97) 
[INFO] [talledLocalContainer] at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56) 
[INFO] [talledLocalContainer] at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72) 
[INFO] [talledLocalContainer] at org.hibernate.impl.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:400) 
[INFO] [talledLocalContainer] at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:351) 
[INFO] [talledLocalContainer] at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1291) 
[INFO] [talledLocalContainer] at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:713) 
[INFO] [talledLocalContainer] at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:121) 
[INFO] [talledLocalContainer] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83) 
[INFO] [talledLocalContainer] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60) 
(...) 

-and-errorリテラル値(それぞれ0と10)を ":offset"と ":limit"に置き換えても正常に動作することがわかりました。これには理由がありますか?名前付きパラメータを取得する方法はありますか?

私は、名前付きクエリでオフセットとリミット値を動的に設定するための配置パラメータを使用するいくつかの例を見てきましたが、私のコードは読みにくいquery.setParameter(1, "someValue");ナンセンスに縮退しません。名前付きパラメータは、その種のガベージコードを取り除くことになっていました。

答えて

17

Hibernateには、実行時にこれらの概念を指定するための特別なAPIがあります。私はそれがこの方法を行うの理由は、データベースのベンダーがどこでどのようにSQLクエリでこれらの概念が指定されているのと大きく異なる点であるので、それは別の上に一つのフォーマットを選択するのが妥当ではないと思う

@NamedQuery(name="MyEntity.findByUser", 
    query="SELECT m FROM MyEntity m WHERE m.owner = :user") // don't put OFFSET or LIMIT here 

... 

entityManager.createNamedQuery("MyEntity.findByUser") 
.setFirstResult(20) // equivalent to OFFSET 
.setMaxResults(5) // equivalent to LIMIT 
.getResultList(); 

、及びこれを試してみてくださいそれらの間で変換しようとするにはあまりにも難しいです。

このように、ダイアレクトの実装では、実行する必要があることを明確に把握してから実行できます。

+3

ありがとうございます。このメソッドは機能します。しかし、明らかになっている理由について私が完全に同意しているかどうかはわかりません。 'OFFSET'と' LIMIT'キーワードはEJBQL仕様の一部です。彼らが仕様に入っているなら、そのようにサポートされるべきです。さらに、それらのサポートが破棄された場合、クエリ内のリテラル値を使用しても失敗するように完全に削除されているはずです。私の見解では、リテラル値が動作し、パラメータ化された値がバグではない現在の状態です。 – aroth

+0

公正なコメント - ポスト – Bohemian

+0

から「明白」が削除されました@これは私にとっても起こりましたが、今回は文字列の値です。私はパラメータをハード値で置き換えるとうまくいきます...私はこの事実の背後にある他のエラーがあると思います –

関連する問題