2011-08-09 23 views
8

Tengo una llamada de criterios de Hibernate que deseo ejecutar en una declaración SQL. Lo que intento hacer es seleccionar instancias de Parent que tengan hijos con una propiedad en un rango de valores (cláusula SQL IN), todo al cargar los elementos secundarios usando una combinación externa. Esto es lo que tengo hasta ahora:Criterios de hibernación con restricciones en niños

Criteria c = session.createCriteria(Parent.class); 

c.createAlias("children", "c", CriteriaSpecification.LEFT_JOIN) 
      .setFetchMode("c", FetchMode.JOIN) 
      .add(Restrictions.in("c.property", properties)); 

c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

return c.list(); 

He aquí algunos datos de ejemplo:

Parent 
Parent ID 
A 
B 
C 

Children 
Child ID Parent ID property 
...   A   0 
...   A   2 
...   A   7 
...   B   1 
...   C   1 
...   C   2 
...   C   3 

Lo que quiero hacer es volver los padres y todos sus hijos si uno de los niños tiene una propiedad igual a mi vincular parámetro (s). Supongamos que propiedades es una matriz que contiene {2}. En este caso, la llamada devolverá los padres A y C pero sus colecciones secundarias contendrán solo el elemento 2. Es decir. Padre [niños]:

A [2] & C [2]

Lo que quiero es:

A [0, 2, 7] & C [1, 2, 3]

Si esto no es un error, parece ser una semántica rota. No veo cómo llamar a A.getChildren() o C.getChildren() y devolver 1 registro se consideraría correcto, esto no es una proyección. Es decir. si aumentamos la consulta para utilizar el valor por defecto seleccionar Obtener, devuelve las colecciones infantiles adecuadas, aunque situado con una multitud de consultas:

c.createAlias("children", "c").add(
     Restrictions.in("c.property", properties)); 

Es esto un error? Si no, ¿cómo puedo lograr el resultado deseado?

Respuesta

1

getChildren() es solo el nombre del getter/setter, su consulta determinará cómo se llenan los objetos.

voy a adivinar aquí que la primera parte escupe

SELECT * FROM Parent 
INNER JOIN Child c ON ... 
WHERE c.property in (x,y,z) 

que no recibe lo que quiere. ¿Qué le gustaría hacer si estuviera escribiendo esto en SQL prima es la siguiente:

SELECT * FROM Parent 
WHERE ParentID IN (SELECT DISTINCT parentID FROM Child WHERE c.property in (x,y,z)) 

reordenando sus criterios de manera apropiada puede hacer el truco si el último no está produciendo esta consulta. (¿Podría también publicar qué hibernación está generando para cada uno?)

+1

Derecho, el SQL es la parte fácil. Lo que estoy buscando son las llamadas de criterios. ;) Además, tenga en cuenta que esto requerirá una combinación externa para poblar las entidades secundarias. –

+0

Así que, ¿la segunda consulta está recibiendo al padre y la carga lenta de los hijos? – dfb

+0

Sí, por cada registro primario devuelto se está ejecutando una consulta secundaria, que es lo que intento evitar. Parece que esto puede ser un defecto, pero tengo curiosidad por saber si alguien tiene una solución: https://hibernate.onjira.com/browse/HHH-3524 –

0

Comenzaría los Criterios con la clase secundaria. Obtendrá una lista con todos los niños, y luego podrá repetir y obtener el padre para cada niño.

2
 Criteria c = session.createCriteria(Parent.class); 

    c.createAlias("children", "children"); 
    c.add(Restrictions.in("children.property", properties)); 

    c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

    return c.list(); 
0

Esto se puede hacer en el trabajo.

Criteria c1 = session.createCriteria(Child.class); 
c1.add(Restrictions.in("property", properties)); 
c1.setProjection(Projections.distinct(Projections.property("parentId"))); 
List<Integer> parentIds = c1.list(); 

Criteria c2 = session.createCriteria(Parent.class); 
c2.createAlias("children", "children"); 
c2.add(Restrictions.in("id", parentIds)); 
return c2.list(); 
Cuestiones relacionadas