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 :

[HIBERNATE 3]Lazy loading


Sujet :

Hibernate Java

  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut [HIBERNATE 3]Lazy loading
    Bonjour, j'utilise Struts et Hibernate 3. Je me pose une question par rapport au "lazy loading"

    Dans mon appli, j'ai un objet persistant MemberDAO. Ce dernier possède une relation one-ton-one vers un objet persistant AccessDAO. AccessDAO à une relation one-to-many vers des objets persistant GroupDAO (correspondant aux différents groupes auxquels est associé le membre).

    Lorsque je recherche un membre, je ne veux pas récupérer sa liste de groupes à chaque fois. J'ai donc mis la collection de groupDAO en lazy="true" dans le fichier de mapping access.hbm.xml.

    Le problème c'est que dans une des pages d'administration, je souhaite afficher une combo affichant les rôles de l'utilisateur que j'édite...

    Pour ce faire, j'utilise la méthode suivante pour récupérer mon membre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
        public MemberDAO findMemberByLogin(String login) {
     
            MemberDAO memberDAO = null;
     
            try {
     
                Session session = HibernateHelper.currentSession();
     
                // Query creation
                Query query = session
                        .createQuery("from MemberDAO as memberDAO where memberDAO.access.login = :login");
                query.setParameter("login", login);
     
                // Loading object
                memberDAO = (MemberDAO) query.uniqueResult();
            } catch (Exception e) {
                logger.logError("Erreur de requte", e);
            } finally {
                HibernateHelper.closeSession();
            }
            return memberDAO;
        }
    Le soucis c'est que mon membre n'a pas sa liste de groupes initialisée
    Dans Hibernate 2, on pouvait initialiser une collection à la demande (dans une session) en faisant un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Hibernate.initialize(dao.saList);
    Ma question est simplement la suivante:
    Dans hibernate 3, comment fait on pour initialiser une collection dans une session et travailler ensuite dessus dans un mode déconnecté??

    Merci d'avance

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  2. #2
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Précise explicitement ta jointure dans ta requete à l'aide d'un "left outer join" : http://www.hibernate.org/hib_docs/v3/reference/fr/html/queryhql.html#queryhql-joins

  3. #3
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    ok je teste ca et je te tiens au courant, merci

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  4. #4
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Sinon, autre solution si tu utilises Spring: http://www.springframework.org/docs/api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html

    Ta transaction est terminée mais ta session reste ouverte pour pouvoir continuer à charger des objets à la demande pour les besoins spécifiques de ta vue.

  5. #5
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Ca a l'air interessant mais n'est il pas préférable de laisser ouverte une session (et donc une connection vers la base) le moins de temps possible afin de la rendre au pool.??

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  6. #6
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Quels sont les choix que tu as ?

    1- tout charger en un seul appel, c'est la première solution que je t'ai donné (généralement avec un appel qui surcharge le mapping qui utilise du lazy loading). -> 1 appel
    2- dans une transaction, charger ton objet et en faisant un appel explicite aux objets dépendants (pour des besoin métiers par exemple) on fait un 2eme appel à la base -> 2appels
    3- dans la transaction, on charge l'objet, on quitte la transaction et pour une problématique de présentation (parceque le modèle retourné est incomplet du fait du lazy loading) on utilise la session pour récupérer les infos complémentaires. -> 2 appels

    Le choix entre le 2 est la 3 est souvent une question de gout. Pour ma part je fais la distinction entre problematique métier et problematique de présentation.
    Si tu dis que tu utilisais avant un "Hibernate.initialize(dao.saList); ", tu te placais dans le cas numéro 2, toutefois je pense qu'un OpenSessionInViewFilter est mieux adapté pour ton besoin.

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    ok effectivement!!!! En tout cas merci pour cette précision mais je pense que je vais garder la première solution étant donné que je ne travaille pas avec Spring


    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  8. #8
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    En fait j'ai toujours un petit soucis de "LazyInitializationException", pourtant j'ai bien modifier la requête de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
        public MemberDAO findMemberByLogin(String login, boolean initializeGroups) {
     
            // DAO to return
            MemberDAO memberDAO = null;
            String queryString = "select memberDAO from MemberDAO as memberDAO where memberDAO.access.login = :login";
            if (initializeGroups) {
                queryString = "select memberDAO from MemberDAO as memberDAO left outer join memberDAO.access.groups where memberDAO.access.login = :login";
            }
            try {
     
                Session session = HibernateHelper.currentSession();
     
                // Query creation
                Query query = session.createQuery(queryString);
                query.setParameter("login", login);
     
                // Loading object
                memberDAO = (MemberDAO) query.uniqueResult();
     
            } catch (Exception e) {
                logger.logError("Erreur de requête", e);
            } finally {
                HibernateHelper.closeSession();
            }
            return memberDAO;
        }
    Lors de l'appel je passe bien true en paramètre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MemberDAO memberDAO = MemberManager.getInstance().findMemberByLogin(username, true);
    mais lorsque plus loin j'appelle la méthode size sur ma liste de groupes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int size = memberDAO.getAccess().getGroups().size();
    une "LazyInitializationException" est levée

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  9. #9
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    from MemberDAO as memberDAO left outer join fetch memberDAO.access.groups where memberDAO.access.login = :login

  10. #10
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Décidement j'ai pas les yeux en face des trous parfois
    J'étais parti sur la section 19 "Section 19.1, « Stratégies de chargement »"...

    Néanmoins Hibernate me lève une exception et me précise que l'objet auquelle est rattachée la collection doit être sélectionné dans la clause select:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list (com.toto.website.hibernate.pojo.GroupDAO -> com.toto.website.hibernate.pojo.AccessDAO) [select memberDAO from com.toto.website.hibernate.pojo.MemberDAO as memberDAO inner join fetch memberDAO.access.groups where memberDAO.access.login = :login]
    j'aimerais ne pas à avoir à récupérer l'objet "accessDAO" via la clause select et donc ne pas avoir à récupérer un Object[] à parser après l'exécution de cette requête, y a t il une solution alternative???

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  11. #11
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    en fait tout marche niquel, la requête est bien la suivante comme tu avais dis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    from MemberDAO as memberDAO inner join fetch memberDAO.access.groups where memberDAO.access.login = :login
    par contre cela ne marche pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select memberDAO from MemberDAO as memberDAO inner join fetch memberDAO.access.groups where memberDAO.access.login = :login
    et cela lève l'exception précédente alors bien penser à ne pas mettre de select!!

    Merci en tout cas pour ton grand coup de main

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  12. #12
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Si tu précises "select memberDAO", la requete SQL générée va juste chercher à ramener les champs de la classe MemberDAO. Je pense que sachant juste cela, tu comprends mieux le message d'erreur (the owner of the fetched association was not present in the select list : les champs de l'objet access ne sont pas dans la requete)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Probleme Hibernate + JPA -> lazy loading non respecté
    Par MikoMax dans le forum Hibernate
    Réponses: 1
    Dernier message: 28/08/2007, 15h13
  2. Réponses: 3
    Dernier message: 10/07/2007, 10h21
  3. Spring hibernate lazy loading
    Par mauroyb0 dans le forum Hibernate
    Réponses: 6
    Dernier message: 09/05/2007, 12h14
  4. Lazy loading et fermeture de session hibernate
    Par BRAUKRIS dans le forum Hibernate
    Réponses: 3
    Dernier message: 20/07/2006, 13h08
  5. [hibernate] problème pour desactiver le lazy loading
    Par agougeon dans le forum Hibernate
    Réponses: 2
    Dernier message: 14/03/2006, 11h20

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