IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Hibernate Java Discussion :

Utilisation "avancée" des projections


Sujet :

Hibernate Java

  1. #1
    Membre régulier Avatar de thibane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Février 2007
    Messages : 143
    Points : 83
    Points
    83
    Par défaut Utilisation "avancée" des projections
    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 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vProjections.add(Projections.property("aliasPrincipal.propriété3"), "propriété3");
    juste avant la projection :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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..
    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 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

    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!

  2. #2
    Membre régulier Avatar de thibane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Février 2007
    Messages : 143
    Points : 83
    Points
    83
    Par défaut
    En attendant de trouver mieux, je suis parti sur une autre solution de secours que celle que j'ai proposé.

    En fait, la lecture des alias dans les projections fonctionne, puisque j'arrive bien à accéder aux propriétés des autres objets via les alias mais c'est bien le ResultTransformer qui pose problème, il ne fait apparemment pas d'introspection pour aller chercher les bons getters/setters dans les objets imbriqués (par l'intermédiaire des alias).

    Du coup, au lieu de mapper à la main les propriétés dans mon Objet1, objet sur lequel j'ai créé le Criteria et type que je voulais avoir en retour, j'utilise bien un ResultTransformer.aliasToBean mais sur un Objet1Custom dans lequel je n'ai en fait que des membres de type primitif (String, Long, etc), que ceux qui m'intéressent évidemment et les getters/setters qui vont avec.

    C'est lourd aussi, mais moins quand même...

    Quand j'aurai le temps, j'essaierai de voir pour surcharger la méthode aliasToBean actuelle et la faire fonctionner avec des objets imbriqués avec les alias, mais en attendant, si ça peut dépanner quelqu'un d'autre...

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo