11

私は以下NamedQueryを機能させようとしています:

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

問題は、これにより、サーバーの起動時に次のスタック トレースで Hibernate が爆発することです。

[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)
(...)

試行錯誤の末、「:offset」と「:limit」をリテラル値 (それぞれ 0 と 10) に置き換えるとうまくいくことがわかりました。これには理由がありますか?名前付きパラメーターをクエリで機能させる方法はありますか?

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

4

1 に答える 1

26

Hibernate には、実行時にこれらの概念を指定するための特別な API があります。これを試して:

@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();

このようにした理由は、SQL クエリのどこでこれらの概念をどのように指定するかについてデータベース ベンダーが大きく異なるためだと思います。

このようにして、方言の実装は何をする必要があるかを明確に認識し、それを行うことができます。

于 2011-07-04T01:53:55.157 に答える