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 :

Stratégies de chargement


Sujet :

Hibernate Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut Stratégies de chargement
    Bonjour,

    J'aimerai être éclairé sur un point, le lazy loading.
    J'ai bien comprit le principe de cette stratégie, mais concrètement, dans le DAO, faut-il laisser ouverte ou fermer la session?

    Car dans certains cas, si je ferme la session j'obtiendrai un "no session or session was closed"!
    Mais si je la laisse ouverte j'obtiens des "Illegal attempt to associate a collection with two open sessions"

    Merci d'avance pour cette petite explication!

  2. #2
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Tout dépend du contexte d'utilisation et du besoin...
    Pour le web, il est fortement recommandé de fermer la session dès que la réponse a été rendue.
    Dans un contexte client lourd (swing par exemple), on peut laisser la session ouverte, ça permettra (entre autre) d'avoir des transactions longues sans nécessiter une complexité dans le code.

    Pour revenir sur le web, généralement, on ouvre la session en début de request et on la ferme une fois la réponse envoyée (le plus simple étant de passer par un filtre). Dans ce cas, même si la DAO a renvoyé des objets non initialisés et que l'usage s'en fait sentir au niveau du rendu (donc d'une page jsp par exemple), l'accès sera possible et hibernate pourra lancer les requêtes complémentaires de chargement.

    C'est ok comme explication ?

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Je comprends plus ou moin tout!
    Mais dans mon cas j'utilise Spring, je récupère donc la sessionFactory dans mes daos, et après je ferme la session à la fin de ceux-ci.

    Petit problème lorsque je consulte par exemple la liste de mon historique, lorsque je veux afficher un détail d'une ligne d'historique, il me dit que la session est fermée!

    Pour le moment tout fonctionne, car la où il râle que la session est fermée, je rajouter la condition !session.isOpen() pour fermer la session.
    Mais je trouve que ce n'est pas très propre dans certains cas la fermer, et dans d'autres la laisser ouverte!

  4. #4
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Ton application est de quel type ? (client lourd / web)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Une application web!

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Yes ca c'est fait!

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    En fait, j'ai une douche dao, et une couche service.
    Dans mon application web, j'appelle la couche service.

    Voici un exemple de méthode de ma couche dao:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        public User getUser(long id) {
            Session session = null;
            try {
                session = this.sessionFactory.openSession();
                return (User) session.load(User.class, Long.valueOf(id));
            } catch (HibernateException e) {
                throw new RuntimeException(e);
            } finally {
                if (session != null) {
                    session.clear();
                    session.close();
                }
            }
        }
    Je ferme ma session partout sauf la où ca pose problème, mais apparement il y a des soucis quand meme...

  9. #9
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Oui, mais là, tu fais sessionFactory.openSession() donc tu créés une connection "locale", ça entre en contradiction avec la session par request

    Il faudrait utiliser sessionFactory.getCurrentSession() et laisser le filtre la fermer à la fin du request.
    En gros, ton code devrait se limiter à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public User getUser(long id) 
    {
        try 
        {
            return (User) sessionFactory.getCurrentSession().load(User.class, Long.valueOf(id));
        } 
        catch (HibernateException e) 
        {
            throw new RuntimeException(e);
        } 
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    D'accord merci, donc je récupère la session, mais où est-elle ouverte pour la première fois??

    (J'utilise Spring, donc ma sessionFactory est configuré via Spring)

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Quand je met juste ça, dans mes test j'obtiens l'erreur suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    java.lang.RuntimeException: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    Je n'ai pas testé dans mon module web, mais je devrais aussi configurer le filtre pour mes tests alors?

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    J'ai trouvé mon bonheur sur ce post:
    http://www.developpez.net/forums/m1666115-10/


    Un grand merci, ca faisait un petit temps que j'avais ce problème

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Une partie de mon problème est résolue, j'ai changé tous mes daos, et j'obtiens maintenant une erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    java.lang.RuntimeException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: be.myPackage.Task.status, no session or session was closed
    C'est bizarre quand meme !
    Tout le reste fonctionne, sauf 9 fonctions de mes services, et toutes la même erreur pour les collections !

    Si tu as un dernier coup de pouce ca m'aiderait vraiment beaucoup!

    Merci bcp

  14. #14
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Ben là, c'est difficile... il faudrait avoir accès au projet...

    Normalement, si tout était correctement paramétré, tu ne devrais pas avoir de problème de lazy loading puisque la session n'est fermée qu'à la fin de la phase de rendu...

    Il reste peut-être un point où tu créés une nouvelle session
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Ca va j'ai trouvé, c'était juste que j'avais juste écrit les paramètres de configuration pour mes daos et pas mes services

    Merci beaucoup

  16. #16
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Points : 9 529
    Points
    9 529
    Billets dans le blog
    1
    Par défaut
    Si je peux me permettre, c'est un peu surprenant de définir ces paramètres à plusieurs endroits
    Il serait peut-être judicieux d'utiliser une classe avec méthode static pour partager un maximum.
    L'exemple typique est le suivant
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    package com.obia.safe.database.utils;
     
    import org.apache.log4j.Logger;
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
     
    public class HibernateUtils 
    {
        private static final SessionFactory sessionFactory;
        private static final Logger logger = Logger.getLogger(HibernateUtils.class);
     
        static 
        {
            try 
            {
                logger.debug("Création Session Factory Hibernate");
                sessionFactory = new Configuration().configure().buildSessionFactory();
            } 
            catch (HibernateException ex) 
            {
                logger.error("Erreur lors de la création de la Session Factory Hibernate : " + ex.getMessage());
                throw new RuntimeException("Problème de configuration : " + ex.getMessage(), ex);
            }
        }
     
        public static final ThreadLocal session = new ThreadLocal();
     
        /**
         *    Récupération de la session Hibernate
         */
        public static Session currentSession() throws HibernateException 
        {
            Session s = (Session) session.get();
     
            // Ouvre une nouvelle Session, si ce Thread n'en a aucune
            if (s == null) 
            {
                logger.debug("Acquisition d'une nouvelle Session Hibernate pour le Thread " + Thread.currentThread().hashCode());
                s = sessionFactory.openSession();
                session.set(s);
            }
     
            logger.debug("Récupération de la Session Hibernate " + s.hashCode() + " pour le Thread " + Thread.currentThread().hashCode());
            return s;
        }
     
        /**
         *    Fermeture de la session Hibernate
         */
        public static void closeSession() throws HibernateException 
        {
            Session s = (Session) session.get();
            if ( s == null ) return ;
     
            logger.debug("Fermeture de la Session Hibernate " + s.hashCode() + " pour le Thread " + Thread.currentThread().hashCode());
            session.set(null);
            s.close();
        }
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  17. #17
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Quand je parlais de configurer aussi pour les services, c'est dans la config de Spring, je ne m'amuse pas à tout recopier dans mes services!

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
      </bean>
     
      <bean id="transactionInterceptor"
        class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager" ref="txManager" />
        <property name="transactionAttributes">
          <props>
            <!-- prop key="insert*">PROPAGATION_REQUIRED</prop>
              <prop key="update*">PROPAGATION_REQUIRED</prop -->
            <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
        </property>
      </bean>
     
    <bean id="autoProxyCreator"
        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="interceptorNames">
          <list>
            <idref local="transactionInterceptor" />
          </list>
        </property>
        <property name="beanNames">
          <list>
            <idref local="applicationDao" />
            <idref local="customerDao" />
            <idref local="historyDao" />
            <idref local="taskDao" />
            <idref local="taskStatusDao" />
            <idref local="taskTypeDao" />
            <idref local="userDao" />
            <idref local="applicationService" />
            <idref local="customerService" />
            <idref local="historyService" />
            <idref local="taskService" />
            <idref local="taskStatusService" />
            <idref local="taskTypeService" />
            <idref local="userService" />
          </list>
        </property>
      </bean>
    J'utilise ceci pour maintenir la session, mais j'ai toujours un soucis avec mes collections ! c'est fou quand meme!

    Dans mes Dao j'utilise juste:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    try {
                return (Task) this.sessionFactory.getCurrentSession().load(Task.class, Long.valueOf(id));
            } catch (HibernateException e) {
                throw new RuntimeException(e);
            }
    Apparement il ne garde pas la session ouverte quand j'appelle les collections!
    N'y a-t-il pas un moyen de charger toute les collections dans l'objet avant de le détacher?

  18. #18
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Il y a plusieurs façon de gérer ton problème:
    (désolé si je répète ce qui a déjà été dit)

    - utiliser le pattern open session in view: on ne ferme la session hibernate qu'après le traitement de la vue, par l'utilisation d'un filtre

    - charger ses collections avant de rendre la vue, en utilisant une requête HQL ou Criteria (attribut fetch)

  19. #19
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 104
    Points : 54
    Points
    54
    Par défaut
    Ok pour le filtre, ca je comprends très bien, mais comment l'utiliser dans mon module core pour mes tests?

    Je l'utilise dans mon module web mais j'ai tjs l'erreur, à mon avis je dois configurer un truc en plus dans Spring, non?

    je vais essayer de charger les collections avec une requête Criteria voir ce que ca donne!

    Merci pour toute l'aide et désolé d'insister mais je suis un peu perdu avec tout ca!

  20. #20
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Tu utilises la classe Spring OpenSessionInViewFilter ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Stratégie de chargement
    Par yacine.dev dans le forum Hibernate
    Réponses: 5
    Dernier message: 07/05/2010, 12h15
  2. Stratégie de chargement
    Par kokumbo dans le forum Hibernate
    Réponses: 6
    Dernier message: 30/01/2008, 17h59

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