2010-08-18 8 views
7

Tengo cuatro tablas:HQL: Fetch Únete Colecciones de la Tabla Eager

RootNode // Will return multiple root nodes 
SubNode // Will return one sub node per root node 
SubNodeChildren1 // Will return multiple for each sub node 
SubNodeChildren2 // Will return multiple for each sub node 

y una estructura de entidad similar:

RootNode -> SubNode -> SubNodeChildren1 
        -> SubNodeChildren2 

necesito una consulta que devolverá todo el RootNodes en la tabla con sus hijos SubNode y SubNode inicializados. Se busca con impaciencia el SubNode, pero los hijos SubNode son flojos.

Sé cómo escribir una consulta que va a LEFT OUTER JOIN FETCH los hijos inmediatos de una tabla y los inicializa en consecuencia. Sin embargo, no tengo idea de cómo agarrar a los niños de una mesa que se busca con entusiasmo de la mesa de alto nivel.

He intentado algo así como:

SELECT rn FROM RootNode AS rn LEFT OUTER JOIN FETCH rn.SubNode.SubNodeChildren1 

pero, esto siempre me da un error que el propietario no es parte de la instrucción SELECT.

Cualquier ayuda es muy apreciada.

Respuesta

11

aquí va referencia Hibernate

La única razón por la que podríamos necesitar un alias es si nos estamos uniendo recursivamente otra colección

Lo que implica la consulta debe ser re-escrito como

select distinct 
    rn 
from 
    RootNode rn 
left join fetch 
    rn.subNode sn 
left join fetch 
    sn.subNodeChildren 

puede

inhabilitar subnodo fetch = FetchType.EAGER y simplemente recuperar lo que realmente desea mediante el uso de consulta HQL - It (consulta HQL) efectivamente anula la combinación externa y declaraciones diferidas del archivo de asignación para asociaciones y colecciones (documentación de referencia de Hibernate) Este enfoque es apoyado por POJO en el libro de Acción.

o permitir la recogida de SubNodeChildren como fetch = FetchType.EAGER

El siguiente ha sido extraído de la hibernación FAQ (El enlace ha sido desactivado (Por lo que yo sé), pero me han guardado antes de desaparecer)

En una aplicación MVC, ¿cómo podemos asegurarnos de que todos los proxies y colecciones perezosas se inicializarán cuando la vista intente acceder a ellos?

Un posible enfoque es dejar la sesión abierta (y la transacción no confirmada) al reenviar a la vista. La sesión/transacción se cerraría/confirmaría después de que la vista se represente, por ejemplo, en un filtro de servlet (otro ejemplo usaría la devolución de llamada ModelLifetime.discard() en Maverick). Una dificultad con este enfoque es asegurarse de que la sesión/transacción se cierra/se retrotrae si se produce una excepción al representar la vista.

...

Otro enfoque es simplemente forzar la inicialización de todos los objetos necesarios utilizando Hibernate.initialize(). Esto es a menudo más sencillo de lo que parece.

+0

+1 Me pregunto por qué [las incorporaciones anidadas] (http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Nested_Joins) no están permitidas en JPA. –

1

Con el fin de conseguir el funcionamiento de consulta, que tenía que hacer un INNER JOIN FETCH en lugar de un LEFT OUTER JOIN FETCH en la entidad ansiosos:

SELECT rn FROM RootNode AS rn INNER JOIN FETCH rn.SubNode AS sn LEFT OUTER JOIN FETCH sn.SubNodeChildren1 LEFT OUTER JOIN FETCH sn.SubNodeChildren2 ... 

Para ser honesto, todavía no estoy muy seguro de por qué se está trabajando con un INNER JOIN FETCH contra un LEFT OUTER JOIN FETCH, pero definitivamente está funcionando exactamente como lo necesito.

+0

Ok (+1) Solo por curiosidad: ¿Sería posible que muestre su fragmento de código entre ** sessionFactory.openSession() y session.close() ** ??? ¿Y su mapeo anotado? –

+0

Guau, esto es vergonzoso ... Su respuesta original fue correcta. El fragmento de código, 'IZQUIERDA EXTERIOR UNIR FETCH rn.SubNode AS sn', era el que necesitaba para que mis entidades funcionaran correctamente. (Toda esta confusión se debió a un problema con mi entorno de prueba) –

Cuestiones relacionadas