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 :

Requête JPQL avec NEW qui prends trop de temps


Sujet :

JPA Java

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut Requête JPQL avec NEW qui prends trop de temps
    Bonjour, je travaille avec Java, jpa et hibernate. J'essaye d'implémenter une requête en JPQL, mais elle prend beaucoup trop de temps (j'ai même dû arréter la programme au bout de 5 minutes), comparé à une requête similaire proche faite en pur SQL, dans les même condition

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select NEW package.CustomObject(co.num, item, dim, mat, pro) from Object1 co LEFT JOIN co.items item LEFT JOIN item.dim dim LEFT JOIN item.mat mat LEFT JOIN item.pro pro
               where co.ins between '2018-12-26 01:00:00' and '2019-06-26 01:00:00' 
                   or co.mod between '2018-12-26 01:00:00' and '2019-06-26 01:00:00'.

    L'object CustomObject 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
        public class CustomObject {
     
        	private String num;
     
        	private OtherCustomObject other;
     
        	public CustomObject(String num, ItemObject item, DimObject dim, MatObject mat, ProObject pro) {
        		this.num = num;
        		this.other = new OtherCustomObject(item, dim, mat, pro);
        	}
     
    }
    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
        public class OtherCustomObject {
     
        	private String property1;
        	private String property2;
        	private String property3;
        	private DimObject  dim;
        	private MatObject  mat;
        	private ProObject  pro;
     
        	public OtherCustomObject(ItemObject item, DimObject dim, MatObject mat, ProObject pro) {
        		this.property1 = item.getProperty1();
        		this.property2 = item.getProperty2();
        		this.property3 = item.getProperty3();
        		this.dim = dim;
        		this.mat = mat;
        		this.pro = pro; 
        	}
        }
    Voici la requête proche écrite en SQL pur

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        select  co.num
        from    table1    co  left join ItemTable item on item.ou = co.ou left join DimTable dim on dim.item_id = item.id left join MatTable mat on mat.item_id = item.id left join ProTable pro on pro.item_id = item.id 
        where   co.ins   between '2018-12-26 01:00:00' and '2019-06-26 01:00:00'
            or  co.mod   between '2018-12-26 01:00:00' and '2019-06-26 01:00:00';

    Cette requête est instantanée. Donc qu'est-ce qu'il ne va pas avec la requête JPQL ?

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Regarde du côté des entités référencées, des fois qu'il y aurait d'autres relations en fetchType.EAGER dedans...
    Sinon, dans la mesure où tu veux accéder à des propriétés sous-jacentes, tu devrais plutôt faire des "left join fetch" (si possible...)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut
    Bonjour OButterlin et merci pour ta réponse.

    Pour ce qui est des relations dans les Objets, il y en a par exemple pour ItemObject 1 manyToOne (EAGER) 9 OneToOne (EAGER), 1 ManyToMany (LAZY) et 1 OneToMany (LAZY). Je n'ai pas bien compris ce que je dois faire avec cela.

    Pour ce que tu dis avec left join fetch, j'ai compris qu'il faut que je les mette plutot que des left join dans ma requête. C'est ça ? J'ai essayé en mettant des left join fetch, mais ça n'améliore pas les perfs

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Alors il y a de fortes probabilités que ce soit les chargements sous-jacents qui ralentissent ta requête.
    Une chose que tu peux faire c'est d'afficher les requêtes générées par Hibernate, ça t'en dira plus...
    Il faut positionner la propriété "hibernate.show_sql" à "true"
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut
    J'ai mis show-sql à true et quand la requête démarre, la seule chose qui est loggé est le log suivant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Hibernate: select co.ou as col_0_0_, item.id as col_1_0_, dim.id as col_2_0_, mat.id as col_3_0_, pro.id as col_4_0_ from table1 co left outer join ItemTable item on (item.ou=co.ou) left outer join DimTable dim on (dim.item_id=item.id) left outer join MatTable mat on (mat.item_id=item.id) left outer join ProTable pro on (pro.item_id=item.id) where co.ins_tms_tm between ? and ? or co.mod_tms_tm between ? and ?
    après, plus rien n'est loggé et l'application continue à tourner sans aucun message

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Donc ça, c'est la requête qu'exécute Hibernate...
    Si tu l'exécutes dans un outil comme Database Developper d'Eclipse (en remplaçant les ? par les bonnes valeurs de paramètres), l'exécution est lente ou rapide ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut
    ce qui me choque, c'est que cette requête ne correspond pas du tout à la requête JPQL.

    Sinon, elle prend une seconde

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    1 seconde c'est plutôt satisfaisant, le problème ne vient donc pas de la requête proprement dite, enfin, je ne pense pas... à moins que l'environnement d'exécution d'hibernate ait quelque chose de particulier mais bon, je n'en sais rien.
    Ce que je te suggère d'essayer maintenant c'est de supprimer le new package.CustomObject(co.num, item, dim, mat, pro) de ta requête et de le remplacer par juste co.num, item, dim, mat, pro
    Si les temps de réponse restent correct (ce que je pense), il se pourrait que le problème soit lié à ta classe CustomObject, peut-être un problème de classLoader ou je ne sais quoi... difficile de dire sans le serveur sous la main...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par flamant Voir le message
    ce qui me choque, c'est que cette requête ne correspond pas du tout à la requête JPQL.
    Oui, c'est normal, le JPQL n'est pas SQL, il faut forcément traduire les informations des classes (via les métadonnées) en quelque chose de compréhensible par le SGBDR.
    Sous tout ce biniou de JPQL, il y a JDBC et donc, du SQL...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut
    Bonjour

    1 seconde c'est plutôt satisfaisant, le problème ne vient donc pas de la requête proprement dite, enfin, je ne pense pas..
    en fait les logs dont j'ai parlé qui sont affichés correspondent au début de la requête mais la requête JPQL continue de tourner indéfiniment sans afficher de log


    Ce que je te suggère d'essayer maintenant c'est de supprimer le new package.CustomObject(co.num, item, dim, mat, pro) de ta requête et de le remplacer par juste co.num, item, dim, mat, pro
    c'est ce que j'ai fait mais le temps de réponse est interminable.

    Il y a donc clairement un problème avec la requête je pense, mais je ne voie pas où

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Tu utilises quelle version d'hibernate ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut
    mes dépendances sont les suivantes

    • hibernate-jcache-5.2.12.Final.jar
    • hibernate-core-5.2.12.Final.jar
    • hibernate-jpa-2.1-api-1.0.0.Final.jar
    • hibernate-commons-annotations-5.0.1.Final.jar
    • hibernate-envers-5.2.12.Final.jar
    • hibernate-validator-5.3.6.Final.jar



    et voici les extrait de mon pom.xml qui contiennent le mot hibernate
    Code XML : 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
    63
    64
     
    <hibernate.version>5.2.12.Final</hibernate.version>
    ...................
    <liquibase-hibernate5.version>3.6</liquibase-hibernate5.version>
    ....................................
    		<dependency>
    			<groupId>com.fasterxml.jackson.datatype</groupId>
    			<artifactId>jackson-datatype-hibernate5</artifactId>
    		</dependency>
    ..................................
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-jcache</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-envers</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-validator</artifactId>
    		</dependency>
    ....................................
    		<dependency>
    			<groupId>org.hibernate</groupId>
    			<artifactId>hibernate-jpamodelgen</artifactId>
    		</dependency>
    .......................................
    			<plugin>
    				<groupId>org.apache.maven.plugins</groupId>
    				<artifactId>maven-compiler-plugin</artifactId>
    				<version>${maven-compiler-plugin.version}</version>
    				<configuration>
    					<annotationProcessorPaths>
    						<path>
    							<groupId>org.mapstruct</groupId>
    							<artifactId>mapstruct-processor</artifactId>
    							<version>${mapstruct.version}</version>
    						</path>
    						<!-- For JPA static metamodel generation -->
    						<path>
    							<groupId>org.hibernate</groupId>
    							<artifactId>hibernate-jpamodelgen</artifactId>
    							<version>${hibernate.version}</version>
    						</path>
    						<path>
    							<groupId>org.projectlombok</groupId>
    							<artifactId>lombok</artifactId>
    							<version>${lombok.version}</version>
    						</path>
    					</annotationProcessorPaths>
    				</configuration>
    			</plugin>
    ............................................
    			<plugin>
    				<groupId>org.liquibase</groupId>
    				<artifactId>liquibase-maven-plugin</artifactId>
    				<version>${liquibase.version}</version>
    				<dependencies>
    					<dependency>
    						<groupId>org.liquibase.ext</groupId>
    						<artifactId>liquibase-hibernate5</artifactId>
    						<version>${liquibase-hibernate5.version}</version>
    					</dependency>

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Ce que je ne comprends pas c'est que si tu lances la requête générée par Hibernate dans un autre outil de requête, l'exécution dure 1 s alors qu'avec Hibernate elle est longue.
    Du coup, ça laisse supposer que c'est le traitement du résultat fait par Hibernate qui met du temps... Je ne vois pas ce qui cloche là
    Il faudrait suivre en debug l'exécution de la requête (en entrant dans le processus) pour essayer de trouver la cause, ça peut être long...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut
    La requête suivante met 937 millisecondes à s'éxécuter et retourne 108348 résultat
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select co.num  from Object1 co LEFT JOIN co.items item LEFT JOIN FETCH DimObject dim on dim.item.id = item.id LEFT JOIN FETCH MatObject mat on mat.item.id= item.id LEFT JOIN FETCH ProObject pro on pro.item.id = item.id
               where co.ins between '2018-12-26 01:00:00' and '2019-06-26 01:00:00' 
                   or co.mod between '2018-12-26 01:00:00' and '2019-06-26 01:00:00'.

    Alors que la requête suivante est sans fin
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select co.num, item, dim, mat, pro from Object1 co LEFT JOIN co.items item LEFT JOIN FETCH DimObject dim on dim.item.id = item.id LEFT JOIN FETCH MatObject mat on mat.item.id= item.id LEFT JOIN FETCH ProObject pro on pro.item.id = item.id
               where co.ins between '2018-12-26 01:00:00' and '2019-06-26 01:00:00' 
                   or co.mod between '2018-12-26 01:00:00' and '2019-06-26 01:00:00'.

    à noter que le LEFT JOIN FETCH ne passe pas pour LEFT JOIN co.items item

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    left join fetch, c'est du JPQL pas du SQL
    La requête qui m'intéresse c'est
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select co.ou as col_0_0_, item.id as col_1_0_, dim.id as col_2_0_, mat.id as col_3_0_, pro.id as col_4_0_ 
    from table1 co left outer join ItemTable item on (item.ou=co.ou) 
    left outer join DimTable dim on (dim.item_id=item.id) 
    left outer join MatTable mat on (mat.item_id=item.id) 
    left outer join ProTable pro on (pro.item_id=item.id) 
    where co.ins_tms_tm between '2018-12-26 01:00:00' and '2019-06-26 01:00:00' 
    or co.mod_tms_tm between '2018-12-26 01:00:00' and '2019-06-26 01:00:00'
    (exécutée dans un outil de requête)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  16. #16
    Membre actif
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    728
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 728
    Points : 250
    Points
    250
    Par défaut
    Je pense que le problème vient du nombre de données: 108348 résultat pour co.num avec les jointure: select co.num from Object1 co LEFT JOIN ...........

    Pour récupérer co.num, item, dim, mat, pro dans les mêmes conditions, ça doit prendre beaucoup de mémoire

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

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    ben c'est sûr qu'avec ce nombre, tu vas bien faire ramer ton serveur
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. [Toutes versions] Requête SQL avec VBA qui ne retourne rien
    Par Roums dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 07/01/2011, 10h37
  2. Réponses: 3
    Dernier message: 21/01/2008, 14h38
  3. Serveur qui prend trop de mémoire
    Par malag dans le forum Langage
    Réponses: 4
    Dernier message: 02/04/2007, 22h05
  4. Réponses: 2
    Dernier message: 18/03/2007, 18h10
  5. Problème de Thread qui prend trop de mémoire
    Par petozak dans le forum Général Java
    Réponses: 20
    Dernier message: 11/12/2006, 15h24

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