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 :

Chargement de données, parcours arbre, Exploitation du cache


Sujet :

Hibernate Java

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 5
    Points : 3
    Points
    3
    Par défaut Chargement de données, parcours arbre, Exploitation du cache
    Bonsoir,
    J'ai une structure de donnée de type arbre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Noeud {
        Integer Id ;//sequence
        Noeud precedent; // référence au noeud precédent
        String donnee;
    }
    Grosso Modo, je developpe un batch et l'algorithme de mon programme part d'un ou plusieurs noeud initiaux (racines) jusqu'a un ou plusieurs noeuds finaux. Ci dessous l'algorithme en pseudo code "java".

    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
     
    recupererSolutions() {
        List racines = getRacines(); // getRacines utilise hibernate pour récuperer l
         while (racines.iteartor.hasnext()) {
              parcourirArbre((Noeud)racines.iteartor.next());
         }
    }
     
    parcourirArbre(Noeud courant) {
       Si (courant==null || isFeuille(courant)) return;
       List suivants = getSuivants(courant) ; // utilise hibernate
       while (suivants.iteartor.hasnext()) {
           parcourirArbre((Noeud)suivants.iteartor.next());
       }
    }
    Les appels à hibernate sont localisés dans getRacines(); et getSuivants(courant) ;

    La requete dans getSuivants et de ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    List getSuivants(courant) {
       Query query = session.getQuery("from Noeud where precedent=:courant").setEntity("courant",courant);
       return query.list();
    }
    Voici mon problème : Hibernate effectue une requete en base pour chaque Noeud suivant. Conséquence mon application est très lente (j'ai des milliers d'enregistrements Noeuds donc des millers d'accès en base).

    Mon idée pour résoudre le problème est de charger tous les Noeuds en mémoire avant l'appel de la fonction récursive parcourirArbre() dans recupererSolutions().
    Je me suis dit qu'hibernate pouvait bien faire ça sans que je me "fatigue" à creer des Map à tire la rigo. Je charge donc tous les noeuds puis j'utilise la même session dans getSuivants().

    En gros :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
       Session s = new SessionImpl(); // donnée membre 
     recupererSolutions() {
        List racines = getRacines(); // getRacines utilise hibernate pour récuperer l
        loadAll(); // Recupère toutes les peristants Noeud en base sur la session S
         while (racines.iteartor.hasnext()) {
              parcourirArbre((Noeud)racines.iteartor.next());
         }
       
       List getSuivants(courant) {
          Query query = session.getQuery("from Noeud where  precedent=:courant",s).setEntity("courant",courant);
       return query.list();
         }
    }
    Voilà, après execution et mesure des performances, j'observe en effet une amélioration d'une facteur d'un peu plus du tiers (1/3).
    Cependant, cette amélioration me semble insuffisante, après tout l'accès mémoire et beaucoup plus rapide qu'une connexion à la base.
    Et lorsque je regarde la log générée par hibernate, il m'indique qu'il execute des prepared statment puis qu'il trouve l'entité en proxy
    Alors je ne comprend pas, hibernate fait t'il réellement un accès en base ? Cette lenteur est elle normale ?? Y'a t'il trop d'objets dans la session et du coup la recherche des entités est plus longue (pb mémoire) ??? Y'at'il des solutions bien connues pour ce genre de problème (parcours d'un arbre)??

    Merci d'avoir lu et, je remercie par avance les bonnes âmes qui se pencherons sur mon problème.

  2. #2
    Membre actif Avatar de mOuLi
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2008
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2008
    Messages : 170
    Points : 257
    Points
    257
    Par défaut
    Déjà je pense que tu devrais activer les logs SQL (positionnement du show_sql à true dans la conf Hibernate) pour voir combien réellement de requêtes sont réalisées par Hibernate.
    A mon avis et vu comment sont structurées les données (association entre un noeud et son père), tu dois avoir une requête par niveau (1 req pour la racine, 1 req pour les fils de la racine, 1 req pour les petit-fils de la racine, etc ...). Donc plus ton arbre est profond, plus tu auras de requêtes.


    Si tu as la main sur la structure des données en base, tu pourras éventuellement utiliser une autre représentation "intervallaire" de ton arbre (tel que décrit ici). Là tu pourras charger ton arbre en une seule requête.

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    J'ai activé show_sql à true et les requêtes sont effectivement exécutés en base . Existe t'il une option dans hibernate pour éviter ceci ?? Sinon je vais tout simplement utiliser des maps pour cacher le chargement.
    Ton lien sur le représentation intervallaire est intéressant mais un changement de structure n'est pas possible. Mais cela pourrait être utile pour le futur.

  4. #4
    Membre actif Avatar de mOuLi
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2008
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2008
    Messages : 170
    Points : 257
    Points
    257
    Par défaut
    Il est évident qu'Hibernate ne peut charger toute ta structure arborescente en une seule fois : sauf erreur de ma part et comme je l'ai précédemment dit, tu dois avoir au mieux N requêtes avec N la profondeur de ton arbre.
    A la rigueur et en utilisant les mécanismes de cascades Hibernate, tu pourrais n'avoir qu'une seule requête HQL qui chargerait en cascade tout l'arbre mais là encore Hibernate devra exécuter N requêtes.

Discussions similaires

  1. [DBA] Chargement de données via txt ou xls
    Par divail dans le forum SQL
    Réponses: 4
    Dernier message: 08/03/2006, 10h07
  2. Réponses: 1
    Dernier message: 09/02/2006, 10h11
  3. Réponses: 1
    Dernier message: 07/12/2005, 17h53
  4. Chargement de données texte.
    Par Guiadeur dans le forum Oracle
    Réponses: 1
    Dernier message: 19/10/2005, 11h42
  5. texture dynamique et chargement de données
    Par Mastero dans le forum DirectX
    Réponses: 6
    Dernier message: 03/05/2005, 14h37

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