2011-07-04 6 views
8

estoy tratando de obtener la siguiente NamedQuery para trabajar:Hibernar: ¿No se puede usar un parámetro con nombre para OFFSET y LIMIT?

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

El problema es que esto hace que Hibernate para explotar con la siguiente pila-trace en el arranque del servidor:

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

Después de algunos ensayos -y-error Encontré que reemplazar ": offset" y ": limit" con valores literales (0 y 10, respectivamente) funcionó bien. ¿Hay alguna razón para esto y hay alguna forma de que los parámetros nombrados funcionen en mi consulta?

He visto otros ejemplos que usan parámetros de posición para establecer dinámicamente los valores de compensación y límite en una consulta con nombre, pero prefiero no tener mi código degenerado en un montón de absurdas query.setParameter(1, "someValue"); ilegibles. Se suponía que los parámetros con nombre eliminaban ese tipo de código de basura.

Respuesta

17

Hibernate tiene una API especial para especificar estos conceptos en tiempo de ejecución. Prueba esto:

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

Supongo que la razón se hace de esta manera es que los proveedores de bases de datos varían mucho en cuanto a cómo y dónde en la consulta SQL se especifican estos conceptos, así que no es razonable elegir un formato u otro, y demasiado difícil de tratar de convertir entre ellos.

De esta manera, la implementación del dialecto sabe claramente lo que se debe hacer y puede hacerlo.

+3

Gracias, ese método funciona. Sin embargo, no estoy seguro de estar completamente de acuerdo sobre la razón por la cual ser obvio. Las palabras clave 'OFFSET' y' LIMIT' son parte de la especificación EJBQL. Y si están en la especificación, deben ser compatibles como tal. Además, si se eliminara el soporte para ellos, debería haberse descartado por completo, de modo que incluso el uso de valores literales en la consulta fallaría. El estado actual de las cosas donde los valores literales funcionan y los valores parametrizados no lo hacen es un error, en mi opinión. – aroth

+0

justo comentario - eliminado "obvio" de la publicación – Bohemian

+0

@aroth: esto también me pasó a mí, pero esta vez es un valor de param string. Funciona bien si reemplazo el parámetro por un valor difícil ... Supongo que hay otro error detrás de este hecho –

Cuestiones relacionadas