Bonjour à tous.
Je souhaiterais restreindre le nombre de colonnes ramenées par un select, ce qui en soi ne semble pas monstrueux...
J'ai une hiérarchie d'objet qui ressemble à ça :
1 2 3 4 5 6 7 8 9 10 11
| Objet1
String propriété1
String propriété2
Objet2 propriété3
Set<Objet3> propriété4
Objet2
String propriété1Objet2
Objet3
String propriété1Objet3 |
Les projections fonctionnent parfaitement, tant que je ne veux pas mapper les résultats dans un objet (Objet1).
J'obtiens donc une liste de tableaux d'Object contenant toutes les propriétés que j'ai projetées.
Sauf que j'aimerais vivement pouvoir récupérer une liste d'Objet1, Objet1 sur lequel j'ai créé le Criteria.
Voici la requête :
1 2 3 4 5 6 7 8 9 10 11 12
|
Criteria vCriteria = (Criteria) getSession().createCriteria(Objet1.class, "aliasPrincipal");
vCriteria.createAlias("aliasPrincipal.propriété3", "aliasSurObjet2");
vCriteria.createAlias("aliasPrincipal.propriété4", "aliasSurObjet3");
ProjectionList vProjections = Projections.projectionList();
vProjections.add(Projections.property("aliasPrincipal.propriété1"), "propriété1");
vProjections.add(Projections.property("aliasPrincipal.propriété2"), "propriété2");
vProjections.add(Projections.property("aliasSurObjet2.propriété1Objet2"), "propriété1Objet2");
vProjections.add(Projections.property("aliasSurObjet3.propriété1Objet3"), "propriété1Objet3");
vCriteria.setProjection(vProjections);
vCriteria.setResultTransformer(new AliasToBeanResultTransformer(Objet1.class));
List<Objet1> vListe = vCriteria.list(); |
A l'exécution de cette requête, j'obtiens une org.hibernate.PropertyNotFoundException me disant qu'il ne trouve pas le setter de la propriété "propriété1Objet2" dans l'Objet1 (normal, le setter est dans l'Objet2). J'ai beau préfixer la propriété par "aliasSurObjet2", il essaye de récupérer le setter "setPropriété1Objet2" de l'Objet1 et pas de l'Objet2.
Du coup, étant donné que AliasToBeanResultTransformer essaye d'injecter les résultats propriété par propriété (à l'aide des setter) (enfin c'est ce que j'ai cru comprendre), j'ai ajouté la projection suivante :
vProjections.add(Projections.property("aliasPrincipal.propriété3"), "propriété3");
juste avant la projection :
vProjections.add(Projections.property("aliasSurObjet2.propriété1Objet2"), "propriété1Objet2");
qui est censée accéder au setter de l'Objet2.
En ajoutant cette projection, je n'ai plus d'erreur. La requête générée est bonne :
1 2 3 4 5 6 7 8 9 10 11 12 13
| select
tab1.propriété1,
tab1.propriété2,
tab2.propriété1Objet2,
tab3.propriété1Objet3
from
table_dObjet1 tab1
inner join
table_dObjet2 tab2
on tab2.id = tab1.id
inner join
table_dObjet3 tab3
on tab3.id = tab1.id |
L'objet Objet2 a bien été instancié mais il est vide. Au moment d'accéder à la propriété propriété1Objet2, Hibernate relance un select * sur Objet2 pour pouvoir l'afficher. C'est le 1er problème.
Je pourrais m'arrêter là, après tout ça fonctionne, j'ai bien réussi à diminuer le nombre de colonnes ramenées par ma requête. A cause du lazy-loading, j'ai certes une requête qui est lancée derrière pour charger une association mais ça fonctionne.
Ca fonctionne, mais pas tout à fait quand même.. ![:(](https://www.developpez.net/forums/images/smilies/icon_sad.gif)
Histoire d'en remettre une couche, je n'arrive absolument pas à accéder à la propriété4 (des Objet3), qui elle est une collection.
Là, quasiment le même constat, en ajoutant une projection :
vProjections.add(Projections.property("aliasPrincipal.propriété4"), "propriété4");
J'obtiens des Objet1 avec une collection d'Objet3 instanciée, mais vide. Et là, dès que j'ajoute une projection derrière :
vProjections.add(Projections.property("aliasSurObjet3.propriété1Objet3"), "propriété4");
pour essayer d'accéder à une propriété de l'Objet3, même exception.
La conclusion que j'en ai tirée ,c'est que le ResultTransformer ne tient pas compte des alias. ![:(](https://www.developpez.net/forums/images/smilies/icon_sad.gif)
Quelqu'un a-t-il déjà rencontré ce problème? Et éventuellement trouvé une solution...?
A première vue, j'en vois une de solution, c'est abandonner le ResultTransformer et mapper les résultats à la main dans mon Objet1. Si vous avez une solution pas trop couteuse pour faire ça (couteuse en temps), je suis toujours preneur...
Merci à vous!
Partager