Utilisez moins de colonnes sur les requêtes SQL avec Hibernate Projections sur une entité avec une relation ManyToOne

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

Question

J'essaie de créer un SQL plus petit, pour éviter le "select * from A". qui est construit par défaut pour les critères de veille prolongée.

Si j'utilise des champs simples (pas de relation) via "Transformers", je peux réussir à avoir ce code SQL:

select description, weight from Dog;

Bonjour, j'ai cette 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;
}

Mon objectif est d’avoir ceci:

select description, weight, owner.name from Dog

J'ai essayé ceci avec des critères (et sous-critères):

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.

Comment utiliser Projections pour obtenir un code SQL plus petit, moins de colonnes? Merci d'avance.

Était-ce utile?

La solution

Tout d'abord,

select description, weight, owner.name from Dog

n'est pas valide SQL. Ce devrait être quelque chose comme

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

à la place. Deuxièmement, pourquoi? Bien qu'il soit possible de faire ce que vous voulez (voir ci-dessous), il est extrêmement détaillé de le faire via l'API Criteria et vous ne gagnez rien à montrer pour cela. Les économies sur le transfert de données pour quelques colonnes sont négligeables, sauf si les colonnes sont de grosses blobs ou si vous sélectionnez des centaines de milliers d'enregistrements. Dans les deux cas, il existe de meilleurs moyens de traiter ce problème.

Quiconque, pour faire ce que vous voulez pour les critères, vous devez joindre la table liée (Personne) via un alias et spécifier une projection sur les principaux critères en utilisant ledit 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"))
 );

Vous trouverez une description et un exemple de ce qui précède dans Documentation de Criteria Projections . Gardez à l'esprit que, une fois exécutés, les critères ci-dessus renverraient une liste de tableaux d'objets. Vous devrez spécifier un ResultTransformer pour convertir les résultats en objets réels.

Autres conseils

Je n'ai pas encore essayé par moi-même, mais je pense que vous pouvez également utiliser un autre constructeur dans votre entité (Pojo) et y passer les colonnes. Voir https://www.iblyts-on-java.org/hibernate- meilleures pratiques / chapitre & 1.2; Pojo " pour une instruction détaillée. Pour moi, il n’est pas encore clair si cela fonctionne aussi pour les relations ManyToOne. Je vais essayer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top