java - teoria - persistencia hibernate
Hibernate Native SQL Query recuperando entidades y colecciones (5)
¿Debería su consulta estar en la tabla de personas en lugar de libros de personas?
session.createSQLQuery("select * from person")
.addEntity("person", Person.class)
.addJoin("book", "person.books")
.list();
Esta es mi situación, tengo dos POJO básicos a los que les he dado un mapa de hibernación simple:
Person
- PersonId
- Name
- Books
Book
- Code
- Description
Mi consulta SQL devuelve 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 de hibernación se ve así:
session.createSQLQuery("select personid, name, code, description from person_books")
.addEntity("person", Person.class)
.addJoin("book", "person.books")
.list();
Esto 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 obtener en mi lista es Objetos de 2 personas con los objetos de libro contenidos en la colección de libros:
List
|- Ben
| |- Book 1
| ''- Book 2
''- John
''- Book 3
Lo que realmente estoy viendo es esto:
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 obtener lo que quiero usando este método?
AFAIK, no es posible recuperar una entidad "fusionada" de una consulta SQL. Obtendrá sólo una matriz de objetos. Lo que hice en esta situación fue que creé un nuevo constructor para mi entidad fusionada que tomó una matriz de objetos como argumento. Entonces construí eso manualmente.
Ampliando la respuesta de Mathews. Para forzar la hibernación para devolver solo una lista de personas, haga:
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();
Las entidades asociadas del libro se buscarán e inicializarán sin una llamada adicional a la db.
El duplicado
.addEntity("p", Person.class)
es necesario porque
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
Opera en la última entidad añadida.
Los siguientes trabajos 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[]
contiene una lista de Person
, cada una de las cuales contiene una lista de Book
. Lo hace en una sola selección de SQL. Creo que tu problema es que no alias específicamente a una persona.
EDITAR: el método devuelve un objeto [], pero la matriz se llena con instancias de persona y solo instancias de persona.
Si Hibernate no entiende cómo asignar a sus clases o si no puede entender cómo asignar la unión, devolverá una lista de objetos. Asegúrese de tener solo una combinación Person
/ Book
en cada línea.
Este comportamiento es causado por un error conocido. Doh, debería haber buscado más!