2011-08-25 4 views
16

Questa è la mia situazione, ho due di base di cui ho dato una semplice mappatura hibernate POJO:Hibernate nativo di query SQL recuperano le entità e le collezioni

Person 
    - PersonId 
    - Name 
    - Books 

Book 
    - Code 
    - Description 

My SQL query restituisce le righe che assomigliano a questo:

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

la mia domanda di sospensione si presenta così:

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

questo è per sezione: 18.1.3 della documentazione hibernate: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/querysql.html#d0e17464

Quello che mi aspettavo di ottenere nella mia lista è 2 persona oggetti con gli oggetti del libro contenuti nella raccolta di libri:

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

Quello che ho sto vedendo in realtà è questa:

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

qualcuno sa se è possibile ottenere ciò che voglio con questo metodo?

risposta

1

La query dovrebbe essere sulla tabella delle persone anziché su person_books?

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

Ho semplificato questo esempio per il gusto di essere conciso. Nel mio uso attuale "person_books" è una query complicata, l'ibernazione non ha modo di ottenere le informazioni per un "libro" senza che io le fornisca nella query. Sto recuperando un numero elevato di righe per Person e preferirei non dover eseguire una query aggiuntiva per trovare i libri per ogni persona. Se non riesco a trovare una soluzione, probabilmente userò questo metodo, ma salterò semplicemente sulle righe in cui la persona non cambia. – Ben

12

le seguenti opere per me:

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

Ciò restituisce un Object[] contenente una lista di Person, ognuno dei quali contiene un elenco di Book s. Lo fa in una singola selezione SQL. Penso che il tuo problema sia che non specifichi in particolare la persona a qualcosa.

MODIFICA: il metodo restituisce un oggetto [], ma l'array viene popolato con istanze Person e solo istanze Person.

Se Hibernate non capisce come eseguire il mapping delle classi o se non riesce a capire come associare il join, restituirà un elenco di oggetti. Assicurati di avere una sola combinazione Person/Book su ciascuna linea.

+0

Quello che mi aspettavo era una lista di Person, non una lista di Object [] con duplicati di persone, quando possedevano più di un libro. Vedi la mia risposta per il link al rapporto sul bug di jira in letargo. – Ben

+0

Mi spiace, per essere chiaro, il metodo restituisce un oggetto [], ma l'array viene popolato con Person e solo Person. Non ho libri lì dentro. Aggiornamento –

1

AFAIK, non è possibile ottenere un'entità "unita" da una query SQL. Tornerai solo ad un array di oggetti. Quello che ho fatto in questa situazione è stato che ho creato un nuovo costruttore per la mia entità unita che ha preso una serie di oggetti come argomento. Poi l'ho costruito manualmente.

33

Espansione sulla risposta di Mathews. Per forzare Hibernate per restituire solo una lista di persone lo fanno:

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(); 

Associated Prenota entità saranno recuperati e inizializzato senza un ulteriore invito al db.

Il duplicato

.addEntity("p", Person.class) 

è necessario perché

.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 

opera l'ultima entità aggiunto.

+1

Questo recupera tutto per Persona e Libro. Cosa succede se si desidera selezionare solo determinate proprietà per migliorare le prestazioni. Come ho capito qualcosa di diverso da * o p. * Non funziona. – T3rm1

+1

L'uso di '{p. *}, {B. *}' Corregge anche un ulteriore problema delle sottosezioni per 'books'. –

Problemi correlati