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

JPA Java Discussion :

[TopLink] couplé à JPA très lent


Sujet :

JPA Java

  1. #1
    Membre expérimenté Avatar de willoi
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    1 355
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 355
    Points : 1 639
    Points
    1 639
    Par défaut [TopLink] couplé à JPA très lent
    Je recupere une grappe d'objet à trois niveaux que j'affiche par la suite dans un arbre.
    Les associations entre ces objets sont des OneToMany.
    Au total , cela represente 1000 objets . Chacun de ces objets 8 propriétés tout au plus.
    Or cela nécessite un peu plus d'une minute pour les extraire et les parcourir
    Quand je regarde de plus près avec le debugger, je m'apercois que les listes générées par JPA/Toplink sont impressionantes et monstrueuses avec des backupValueHolder,des unitOfWorkValueHolder etc ...

    Quelqu'un aurait une idée sur ce problème ?

  2. #2
    Expert éminent

    Avatar de christopheJ
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 600
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France, Indre et Loire (Centre)

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 600
    Points : 8 235
    Points
    8 235
    Par défaut
    Par défaut la stratégie d'un oneToMany pour le fetch est lazy, ce qui explique les valueHolders.

    essaie de modifier tes annotations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @OneToMany(fetch=FetchType.EAGER)

  3. #3
    Membre expérimenté Avatar de willoi
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    1 355
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 355
    Points : 1 639
    Points
    1 639
    Par défaut
    Oui super, cela fonctionne. Je suis passé à 20 secondes.

    Je ne mets pas ce post comme résolu encore, car j'ai encore quelques doutes.
    Par contre, cela peut -il avoir des conséquences sur la façon dont seron persistés et rafraichis mes objets ?

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 40
    Points : 47
    Points
    47
    Par défaut
    D'une manière générale, je pense que ce n'est pas une bonne idée de tout passer en eager. En effet, cela implique que dès que l'on accède à un objet, il va récupérer toutes ses associations (OneToMany). Cela peut avoir des conséquences désastreuse sur les performances.
    Il vaut mieux effectuer des "join fetch" dans les requêtes pour récupérer les associations.

  5. #5
    Membre expérimenté Avatar de willoi
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    1 355
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 355
    Points : 1 639
    Points
    1 639
    Par défaut
    D'accord, mais dans mon cas, je ne réalise aucune requete car j'accède à mes listes d'objets par un getter sur ces memes listes.
    C'est donc le moteur de persistence qui se charge d'éxécuter ses propres requêtes !!!
    Et visiblement, les objets retournés n'ont pas l'air adéquats.
    Car globalement, ce que je veux récupérer représente 800 Ko, et 20 secondes ca reste beaucoup à mon goût.

  6. #6
    Expert éminent
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Points : 7 679
    Points
    7 679
    Par défaut
    Ce que alpha.Omega voulait dire est que tu peux modifier la requête qui récupère le premier niveau pour qu'elle fait un join avec les desecendants, réduisant ainsi le nombre total de requêtes:
    La section 7.3 de la doc d'Hibernate par exemple.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 40
    Points : 47
    Points
    47
    Par défaut
    Oui merci djo.mos d'expliciter mes obscurs propos
    Willoi, si je comprends bien ton entity (la racine de ton arbre) est attaché, et tu le parcours ensuite. Mais comment fais-tu pour récupérer cette racine ?

    Sinon, pour résoudre ce type de problème lié aux performances des outils de mapping, il peut être très utile d'activer l'affichage des requêtes. Il suffit de rajouter dans persistence.xml:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <property name="hibernate.show_sql" value="true" />
    Ca c'est pour hibernate, mais pour Toplink, je ne sais pas...

  8. #8
    Membre expérimenté Avatar de willoi
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    1 355
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 355
    Points : 1 639
    Points
    1 639
    Par défaut
    Pour recuperer la racine, je pars d'une liste d'objets du 1er niveau.
    La racine est objet graphique non persisté.

    Je ne comprends pas en quoi le fait d'activer l'option sur les traces pourrait améliorer mes performances ?
    C'etait activé avant, je l'ai enlevé afin d'éviter de surcharger la console en traces.

    djo.mos
    Ce que alpha.Omega voulait dire est que tu peux modifier la requête qui récupère le premier niveau pour qu'elle fait un join avec les desecendants, réduisant ainsi le nombre total de requêtes:
    La section 7.3 de la doc d'Hibernate par exemple.
    Ma requete premier niveau se fait sans join :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Collection < IPPP > resultatPPP = getJpaTemplate().find("select o from PPP o");
    Je ne vois pas plus simple. Et comme ces objets 1er niveau ont des associations OneToMany, les objets de 2nd et 3eme niveaux sont chargés automatiquement.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    40
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 40
    Points : 47
    Points
    47
    Par défaut
    Activer les requêtes sql va te permettre de contrôler plus finement ce que toplink fait et voir si les requêtes effectuées ne sont pas superflues (et détecter par exemple un n+1 select).

  10. #10
    Membre expérimenté Avatar de willoi
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    1 355
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 355
    Points : 1 639
    Points
    1 639
    Par défaut
    Bon, j'ai suivi tes conseils et j'ai remis à true le show_sql.
    Ca m'a permis de voir que j'ai des objets qui sont chargés bien que je le souhaite pas.
    Sur mes objets de 1er niveau j'ai aussi deux relations ManyToMany avec une autre classe.
    Quand j'ai le fetch à EAGER, ces objets associés sont chargés bien que je n'accède à aucun getter sur la liste de ces objets !!!

    Autre conséquence de la 1ère modification effectuée, c'est à dire après avoir mis le fecth à EAGER sur mes objets de 2nd niveau, cette liste est également chargée sans que j'accède au getter!!!

    Je commence à m'y perdre un peu et surtout ne comprends pas pourquoi des opérations aussi simples puissent prendre autant de temps.

  11. #11
    Expert éminent

    Avatar de christopheJ
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 600
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France, Indre et Loire (Centre)

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 600
    Points : 8 235
    Points
    8 235
    Par défaut
    Grosso modo, le principe est le suivant :
    tu as un graph d'objet dépendant les uns des autres, tu as alors trois cas :
    - tu utilises em.find(..) avec un fetch eager, le système charge tous les objects d'un coup avant de te donner le résultat. pb : on peut charger beaucoup d'objets inutile.
    - tu utilises em.find(..) avec un fetch lazy : le système charge l'objet racine et pose des valueHolder sur les suivant dans le graph. Si tu appeles un getter, il retourne cherche l'objet concerné. pb: beaucoup d'aller retour vers la base.
    - tu utilises em.createNamedQuery(...) avec un fetch lazy : le système charge l'objet racine ainsi que ceux qui sont explicitement déclaré dans la requete avec des "join".

    Prend le temps de réfléchir à ce que tu veux vraiment dans tes objets pour choisir les fetch eager ou lazy et éventuellement l'utilisation d'une NamedQuery.

  12. #12
    Membre expérimenté Avatar de willoi
    Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    1 355
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 355
    Points : 1 639
    Points
    1 639
    Par défaut
    Merci à tous.
    Vous m'avez aidé à comprendre ce que je faisais.

    Finalement, j'ai tout laissé en LAZY et j'ai ecris certaines requetes JPAQL en EAGER pour des besoins précis comme le chargement de mon arbre.

    Ce qui me parait etre le compromis le plus acceptable.

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

Discussions similaires

  1. BDD sur réseau très très très lent...
    Par ericain dans le forum Access
    Réponses: 12
    Dernier message: 20/02/2015, 17h17
  2. Ouverture et fermeture de base très lent...
    Par Tofdelille dans le forum Installation
    Réponses: 6
    Dernier message: 19/09/2006, 18h51
  3. [Lomboz] Editeur jsp très lent
    Par lr dans le forum Eclipse Java
    Réponses: 10
    Dernier message: 29/01/2005, 19h43
  4. SQL Server trés lent
    Par arwen dans le forum MS SQL Server
    Réponses: 18
    Dernier message: 07/11/2003, 14h45

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