Hibernate:无法对 OFFSET 和 LIMIT 使用命名参数?
我正在尝试让以下 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)
(...)
经过一番尝试和错误后,我发现替换“带有文字值(分别为 0 和 10)的 :offset" 和 ":limit" 效果很好。这有什么原因吗?有没有办法让命名参数在我的查询中工作?
我见过一些其他示例,它们使用定位参数在命名查询中动态设置偏移量和限制值,但我不想让我的代码退化为一堆不可读的 query.setParameter(1, "someValue ”);
废话。命名参数应该消除这种垃圾代码。
I'm trying to get the following NamedQuery
to work:
@NamedQuery(name="MyEntity.findByUser", query="SELECT m FROM MyEntity m WHERE m.owner = :user OFFSET :offset LIMIT :limit")
The problem is that this causes Hibernate to explode with the following stack-trace upon server startup:
[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)
(...)
After some trial-and-error I found that replacing ":offset" and ":limit" with literal values (0 and 10, respectively) worked fine. Is there a reason for this, and is there a way to get the named parameters to work in my query?
I've seen some other examples that use positioned parameters to dynamically set the offset and limit values in a named query, but I'd rather not have my code degenerate into a bunch of unreadable query.setParameter(1, "someValue");
nonsense. Named parameters were supposed to get rid of that kind of garbage code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Hibernate 有一个特殊的 API 用于在运行时指定这些概念。试试这个:
我猜这样做的原因是数据库供应商在 SQL 查询中如何以及在何处指定这些概念方面差异很大,因此选择一种格式而不是另一种格式是不合理的,并且很难尝试在它们之间进行转换他们。
这样,方言实现就清楚地知道需要做什么,然后就可以去做。
Hibernate has a special API for specifying these concepts at runtime. Try this:
I guess the reason it's done this way is that database vendors vary greatly as to how and where in the SQL query these concepts are specified, so it's not reasonable to pick one format over another, and too hard to try to convert between them.
This way, the dialect implementation knows clearly what needs to be done, and can then do it.