2011-08-25 30 views
16

Esta es mi situación, tengo dos básica de la que me he dado un simple mapeo de hibernación POJO:entidades Hibernate nativo de consultas SQL recuperar y colecciones

Person 
    - PersonId 
    - Name 
    - Books 

Book 
    - Code 
    - Description 

Mi consulta SQL devuelve las filas que se ven así:

PERSONID NAME  CODE DESCRIPTION 
-------- ---------- ---- ----------- 
1  BEN  1234 BOOK 1 
1  BEN  5678 BOOK 2 
2  JOHN  9012 BOOK 3 

Mi consulta hibernación se ve así:

session.createSQLQuery("select personid, name, code, description from person_books") 
     .addEntity("person", Person.class) 
     .addJoin("book", "person.books") 
     .list(); 

este es por sección: 18.1.3 de la documentación de hibernación: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/querysql.html#d0e17464

Lo que espero estar en mi lista es 2 Persona objetos con los objetos contenidos en el libro de la colección de libros:

List 
|- Ben 
| |- Book 1 
| '- Book 2 
'- John 
    '- Book 3 

Lo que en realidad estoy viendo es la siguiente:

List 
|- Object[] 
| |- Ben 
| | |- Book 1 
| | '- Book 2 
| '- Book 1 
|- Object[] 
| |- Ben 
| | |- Book 1 
| | '- Book 2 
| '- Book 2 
'- Object[] 
    |- John 
    | '- Book 3 
    '- Book 3 

¿alguien sabe si es posible conseguir lo que quiero usar este método?

Respuesta

1

¿Debe su consulta estar en la tabla de personas en lugar de libros_personales?

session.createSQLQuery("select * from person") 
    .addEntity("person", Person.class) 
    .addJoin("book", "person.books") 
    .list(); 
+0

He simplificado este ejemplo por el simple hecho de ser conciso. En mi uso real "person_books" es una consulta complicada, hibernate no tiene forma de obtener la información para un "libro" sin que yo lo proporcione en la consulta. Estoy recuperando una gran cantidad de filas para Person y preferiría no tener que realizar una consulta adicional para encontrar los Libros para cada Persona. Si no puedo encontrar una solución, probablemente usaré este método, pero solo saltaré las filas donde la Persona no cambia. – Ben

12

Los siguientes obras para mí:

session.createSQLQuery("select p.*, b.* from person p, book b where <complicated join>"). 
.addEntity("person", Person.class).addJoin("book", "person.books").list(); 

Esto devuelve un Object[] que contiene una lista de Person, cada una de las cuales contiene una lista de Book s. Lo hace en una sola selección SQL. Creo que tu problema es que no alias específicamente a ninguna persona.

EDITAR: El método devuelve un Objeto [], pero la matriz se rellena con instancias de Persona y solo instancias de Persona.

Si Hibernate no entiende cómo mapear a sus clases o si no puede entender cómo mapear la unión, devolverá una lista de objetos. Asegúrese de tener solo una combinación de Person/Book en cada línea.

+0

Lo que esperaba era una lista de Persona, no una lista de Objeto [] con duplicados de personas, cuando poseen más de un libro. Vea mi respuesta para el enlace al informe de hibernate jira bug. – Ben

+0

Lo siento, para aclararme, el método devuelve un Objeto [], pero la matriz se rellena con Persona, y solo Persona. No tengo ningún libro ahí. –

1

AFAIK, no es posible recuperar una entidad "fusionada" de una consulta SQL. Recibirás solo una matriz de objetos. Lo que hice en esta situación fue que creé un nuevo constructor para mi entidad combinada que tomó una matriz de objetos como argumento. Luego lo construí manualmente.

33

Expandiendo la respuesta de Mathews. Para forzar a Hibernate sólo para devolver una lista de las personas que lo hacen:

List<Person> peopleWithBooks = session.createSQLQuery(
    "select {p.*}, {b.*} from person p, book b where <complicated join>"). 
    .addEntity("p", Person.class) 
    .addJoin("b", "p.books") 
    .addEntity("p", Person.class) 
    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 
    .list(); 

Libro Asociado entidades tendrán que descargar e inicializado sin una llamada adicional a la db.

El duplicado

.addEntity("p", Person.class) 

es necesario porque

.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 

funciona con la última entidad añadió.

+1

Esto podría obtener todo para Person y Book. ¿Qué sucede si quiere seleccionar solo ciertas propiedades para mejorar el rendimiento? Como entiendo, cualquier cosa que no sea * o p. * No funciona. – T3rm1

+1

El uso de '{p. *}, {B. *}' También corrige un problema de subselecciones adicionales para 'books'. –

Cuestiones relacionadas