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.