Utilizzare meno colonne nella query SQL tramite Proiezioni di ibernazione sull'entità con relazione ManyToOne

StackOverflow https://stackoverflow.com/questions/1618394

Domanda

Sto cercando di creare un SQL più piccolo, per evitare " selezionare * da A " che viene creato per impostazione predefinita per i criteri di ibernazione.

Se utilizzo campi semplici (nessuna relazione), tramite " Transformers " ;, posso riuscire a disporre di questo SQL:

select description, weight from Dog;

Ciao, ho questa Entità:

@Entity
public class Dog
{
   Long id;
   String description;
   Double weight;
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "person_id", nullable = false)
   Person owner;
}

@Entity
public class Person
{
   Long id;
   String name;
   Double height;
   Date birthDate;
}

Il mio obiettivo è quello di avere questo:

select description, weight, owner.name from Dog

L'ho provato con Criteria (e subcriteria):

Criteria dogCriteria = sess.createCriteria(Dog.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("description"), description);
proList.add(Projections.property("weight"), weigth);
dogCriteria.setProjection(proList);

Criteria personCriteria = dogCriteria.createCriteria("owner");
ProjectionList ownerProList = Projections.projectionList();
ownerProList.add(Projections.property("name"), description);    
dogCriteria.setProjection(ownerProList);  //After this line,  debugger shows that the
                                          //projection on dogCriteria gets overriden
                                          //and the query fails, because "name" is
                                          //not a field of Dog entity.

Come dovrei usare Proiezioni, per ottenere un SQL più piccolo, meno colonne? Grazie in anticipo.

È stato utile?

Soluzione

Prima di tutto,

select description, weight, owner.name from Dog

non è SQL valido. Dovrebbe essere qualcosa di simile

select description, weight, Person.name
 from Dog join Person on Dog.person_id = Person.id

, invece. Secondo, perché? Sebbene sia possibile fare ciò che vuoi (vedi sotto), è estremamente dettagliato farlo tramite l'API Criteria e non ottieni nulla da mostrare per questo. I risparmi sul trasferimento di dati per un paio di colonne sono trascurabili a meno che tali colonne non siano enormi BLOB o non si selezionino centinaia di migliaia di record. In entrambi i casi ci sono modi migliori per affrontare questo problema.

In ogni caso, per fare ciò che desideri per i criteri, devi unirti alla tabella collegata (Persona) tramite alias e specificare la proiezione sui criteri principali usando detto alias:

Criteria criteria = session.createCriteria(Dog.class, "dog")
 .createAlias("owner", "own")
 .setProjection( Projections.projectionList()
   .add(Projections.property("dog.description"))
   .add(Projections.property("dog.weight"))
   .add(Projections.property("own.name"))
 );

C'è una descrizione e un esempio di quanto sopra in Documentazione sulle proiezioni di criteri . Tenere presente che, una volta eseguito, i criteri sopra riportati restituiscono un elenco di matrici di oggetti. Dovrai specificare un ResultTransformer per convertire i risultati in oggetti reali.

Altri suggerimenti

Non l'ho ancora provato da solo, ma penso che puoi anche usare un altro costruttore nella tua Entità (Pojo) e passare lì le colonne. Vedi https://www.thoughts-on-java.org/hibernate- best practice / capitolo "1.2 Pojo" per un'istruzione dettagliata. Anche per me non è ancora chiaro se questo funziona anche per le relazioni ManyToOne. Proverò.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top