2008-09-17 16 views
18

Para resumir: hibernate no admite proyecciones y consulta por ejemplo? He encontrado este post:Hibernate Query por ejemplo y proyecciones

El código es la siguiente:

User usr = new User(); 
usr.setCity = 'TEST'; 
getCurrentSession().createCriteria(User.class) 
.setProjection(Projections.distinct(Projections.projectionList() 
.add(Projections.property("name"), "name") 
.add(Projections.property("city"), "city"))) 
.add(Example.create(usr)) 

Al igual que el otro cartel, dijo, el SQL generado sigue teniendo una clase donde refering sólo y0_ =? en lugar de this_.city.

Ya probé varios enfoques, y busqué el rastreador de problemas pero no encontré nada sobre esto.

Incluso he intentado utilizar alias de proyección y transformadores, pero no funciona:

User usr = new User(); 
usr.setCity = 'TEST'; 
getCurrentSession().createCriteria(User.class) 
.setProjection(Projections.distinct(Projections.projectionList() 
.add(Projections.property("name"), "name") 
.add(Projections.property("city"), "city"))) 
.add(Example.create(usr)).setResultTransformer(Transformers.aliasToBean(User.class)); 

alguien ha utilizado proyecciones y consulta por ejemplo?

+0

¿podría mostrar el sql completo generado? –

+0

Agregué una solución que incluye el SQL generado cuando tenía un problema similar. –

Respuesta

15

¿Puedo ver su clase de usuario? Esto es solo usando restricciones a continuación. No veo por qué las Restricciones serían realmente diferentes a los Ejemplos (creo que los campos nulos son ignorados por defecto en los ejemplos).

getCurrentSession().createCriteria(User.class) 
.setProjection(Projections.distinct(Projections.projectionList() 
.add(Projections.property("name"), "name") 
.add(Projections.property("city"), "city"))) 
.add(Restrictions.eq("city", "TEST"))) 
.setResultTransformer(Transformers.aliasToBean(User.class)) 
.list(); 

Nunca he usado alaistToBean, pero acabo de leer al respecto. También podría simplemente recorrer los resultados ...

List<Object> rows = criteria.list(); 
for(Object r: rows){ 
    Object[] row = (Object[]) r; 
    Type t = ((<Type>) row[0]); 
} 

Si lo tiene, puede llenar manualmente el usuario usted mismo de esa manera.

Es difícil ver el problema sin más información para diagnosticar el problema.

43

El problema parece ocurrir cuando tiene un alias con el mismo nombre que la propiedad de los objetos. Hibernate parece recoger el alias y usarlo en sql. Encontré esto documentado here y here, y creo que es un error en Hibernate, aunque no estoy seguro de que el equipo de Hibernate esté de acuerdo.

De cualquier manera, he encontrado un trabajo simple que funciona en mi caso. Su experiencia puede ser diferente. Los detalles están por debajo, he tratado de simplificar el código para esta muestra así que me disculpo por cualquier error u errata:

Criteria criteria = session.createCriteria(MyClass.class) 
    .setProjection(Projections.projectionList() 
     .add(Projections.property("sectionHeader"), "sectionHeader") 
     .add(Projections.property("subSectionHeader"), "subSectionHeader") 
     .add(Projections.property("sectionNumber"), "sectionNumber")) 
    .add(Restrictions.ilike("sectionHeader", sectionHeaderVar)) // <- Problem! 
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class)); 

produciría este SQL:

select 
    this_.SECTION_HEADER as y1_, 
    this_.SUB_SECTION_HEADER as y2_, 
    this_.SECTION_NUMBER as y3_, 
from 
    MY_TABLE this_ 
where 
    (lower(y1_) like ?) 

que estaba causando un error: java .sql.SQLException: ORA-00904: "Y1_": identificador no válido

Pero, cuando he cambiado de restricción de utilizar "este", así:

Criteria criteria = session.createCriteria(MyClass.class) 
    .setProjection(Projections.projectionList() 
     .add(Projections.property("sectionHeader"), "sectionHeader") 
     .add(Projections.property("subSectionHeader"), "subSectionHeader") 
     .add(Projections.property("sectionNumber"), "sectionNumber")) 
    .add(Restrictions.ilike("this.sectionHeader", sectionHeaderVar)) // <- Problem Solved! 
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class)); 

Produjo el sql siguiente y mi problema se resolvió.

select 
    this_.SECTION_HEADER as y1_, 
    this_.SUB_SECTION_HEADER as y2_, 
    this_.SECTION_NUMBER as y3_, 
from 
    MY_TABLE this_ 
where 
    (lower(this_.SECTION_HEADER) like ?) 

Thats, it! Una solución bastante simple para un problema doloroso. No sé cómo esta solución se traduciría en un problema de consulta por ejemplo, pero puede acercarlo más.

+2

Paul: Me alegra que haya ayudado. Me ha sorprendido que esta respuesta haya pasado desapercibida mientras parezca ser un gran problema y esta solución no sea intuitiva ni documentada. –

+0

El error relacionado con Hibernate es https://hibernate.onjira.com/browse/HHH-817 y se ha marcado como corregido en la versión 3.6.0Beta4 de Hibernate. – FGreg

+0

@RyanCook ¡Hola! Esta solución funciona, pero me preguntaba si había alguna solución con los Ejemplos, ya que podemos tener hasta 10 filtros (es decir, 10 Restricciones) y tendríamos que verificar para cada uno si el campo es nulo o está vacío). – Tarek

0

Me enfrenta un problema similar. Estoy usando Consulta por ejemplo y quiero ordenar los resultados por un campo personalizado. En SQL haría algo como:

select pageNo, abs(pageNo - 434) as diff 
from relA 
where year = 2009 
order by diff 

Funciona bien sin la orden por cláusula. Lo que tengo es

Criteria crit = getSession().createCriteria(Entity.class); 
crit.add(exampleObject); 
ProjectionList pl = Projections.projectionList(); 
pl.add(Projections.property("id")); 
pl.add(Projections.sqlProjection("abs(`pageNo`-"+pageNo+") as diff", new String[] {"diff"}, types)); 
crit.setProjection(pl); 

Pero cuando agrego

crit.addOrder(Order.asc("diff")); 

recibo una org.hibernate.QueryException : no se pudo resolver la propiedad: diff excepción. Solución con este tampoco funciona.

PD: ya que no pude encontrar ninguna documentación elaborada en el uso de QBE para la hibernación, todo lo anterior es el enfoque principalmente y error juicio

6

El verdadero problema aquí es que hay un error en hibernación donde se utiliza alias de lista de selección en la cláusula-where:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-817

Sólo en caso de las tierras de alguien aquí en busca de respuestas, vaya mira el billete. Me tomó 5 años arreglarlo, pero en teoría estará en uno de los próximos lanzamientos y luego sospecho que su problema desaparecerá.

-1

Realmente no lo creo, lo que puedo encontrar es la palabra "esto". hace que hibernate no incluya ninguna restricción en su consulta, lo que significa que obtuvo todas las listas de registros. Sobre el error de hibernación que se informó, puedo ver que se informó como corregido, pero no pude descargar el parche.

0
ProjectionList pl = Projections.projectionList(); 
pl.add(Projections.property("id")); 
pl.add(Projections.sqlProjection("abs(`pageNo`-" + pageNo + ") as diff", new String[] {"diff"}, types), diff); ---- solution 
crit.addOrder(Order.asc("diff")); 
crit.setProjection(pl); 
+0

agregue alias después de sqlProjection, que se utilizará en el pedido – singh

Cuestiones relacionadas