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 :

Requête générée par Hibernate non conforme à la requête écrite


Sujet :

Hibernate Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut Requête générée par Hibernate non conforme à la requête écrite
    Bonjour, il m'arrive quelque chose d'incroyable. Je travaille sur une application spring boot Hibernate qui est générée par jhipster. Je fais une simple requête qui ressemble à la suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select item from ItemObject item where (item.ins between :dateBegin and :dateEnd) or (item.mod between :dateBegin and :dateEnd)
    J'ai mis show_sql = true et je peux voir la requête générée par Hibernate. Tout d'abord la requête traduite par Hibernate est conforme à la requête précédente. Elle est affichée dans la console. Puis, après une seconde une énorme requête qui s'étale sur plusieurs dizaines de pages est affichée dans ma console. La requête est sans fin en terme de longueur et de temps qu'elle prend. C'est incroyable. Je n'ai jamais vu cela. D'autant plus que cette requête marchait normalement avant et était quasi instantanée. Je ne peux pas vous montrer la requête générée maintenant car je ne suis pas au bureau. Je le rajouterai Lundi matin. Pouvez vous m'aider ?

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut
    Bonjour, en fait le programme me génère une requête hibernate pour chaque association de ItemObject avec à chaque fois des left outer join avec les autres table, et Je ne comprend pas pourquoi il fait ça

  3. #3
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    485
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 485
    Billets dans le blog
    5
    Par défaut
    Il faudrait donner le code de l'objet ItemObject pour que l'on puisse t'aider.

    Mais j'ai quand même une idée sur la question.
    Je pense que tu as un problème de LAZY/EAGER.

    Prenons le cas d'une classe Auteur qui a des Livre.

    Si on est LAZY de Auteur vers Livre, Hibernate (JPA) charge les auteurs mais pas les livres.
    Mais si on est EAGER, Hibernate (JPA) charge les auteurs, mais aussi les livres qui sont liés en BDD aux auteurs, générant des requêtes en plus.

    Cette question est vitale pour les performance.
    Si il y a des EAGER partout, je te laisse imaginer le nombre de requêtes SQL que Hibernate/JPA générera.

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    729
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut
    J'ai un énorme indice : quand j'utilise cette requête dans la même méthode dans les mêmes conditions, avec les mêmes entrées, mais depuis une autre méthode, elle prend 2,5 secondes et sans problèmes

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 729
    Par défaut
    Bonjour, je vais expliquer dans quel cas ma requête passe sans problème. Voici mon model:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
               MainObject----ItemObject------------Property1Object
                                 |             |---Property2Object
                                 |             |---Property3Object
                               -----           |---Property4Object
                               | | |
                             Assoc
                              | | |
                          PaObject
    Je vous rapelle que le but soit que ma requête suivante soit éxecuté sans problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        select item from ItemObject item where (item.ins between :dateBegin and :dateEnd) or (item.mod between :dateBegin and :dateEnd)
    Si, avant d'executer la requête précédente, je passe les 2 étapes suivantes, il n'y a pas de problème, et je ne sais pas pourquoi.

    STEP 1 : faire une requête sur MainObject pour retirer tous les objets qui ont été insérés ou modifiés. Cette étape n'est pas obligatoire (je veux dire que ce qui fait passer ma requête objectif sans problème est l'étape STEP2). C'est une étape préparatoire à STEP2

    STEP2: Après STEP1, j'ai une liste List<MainObject> mainObjectsList . J'exécute le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        List<CustomObject> customObjects = new ArrayList<CustomObject>();
        for (MainObject mainObject : mainObjectsList) {
              customObjects.addAll(constructCustomObjectFromMainObject(mainObject));
        }
    Avec CustomObject qui 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
     
        public class CustomObject    {
        	private static final long serialVersionUID = 4L;
     
        	private String itemProperty1;
        	private String itemProperty2;
        	private String itemProperty3;
        	private String itemProperty4;
        	List<PaObject> paObjectList;
        	private Property1Object  property1Object;
        	private Property2Object  property2Object;
        	private Property3Object  property3Object;
        	private Property4Object  property4Object;
        }
    et la méthode constructCustomObjectFromMainObject qui est la suivante
    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
     
            private  List<CustomObject> constructCustomObjectFromMainObject(MainObject mainObject) {
            	List<CustomObject> customObjectList = new ArrayList<CustomObject>();
            	for (ItemObject item : mainObject.getItems()) {
            		customObjectList.add(constructCustomObject(item, true, true, true, true));
            	}
            	return customObjectList;
            }
     
           private CustomObject constructCustomObject(ItemObject item, boolean property1Flag, boolean property2Flag, boolean property3Flag, boolean property4Flag) {
            	CustomObject customObject = new CustomObject();
            	customObject.setItemProperty1(item.getProperty1());
            	customObject.setItemProperty2(item.getProperty2());
            	customObject.setItemProperty3(item.getProperty3());
            	customObject.setItemProperty4(item.getProperty4());
        	        Set<Assoc> assocSet = item.getAssoc();
        	        List<PaObject> paObjectList = new ArrayList<PaObject>();
        	        for (Assoc assoc : assocSet) {
        		      paObjectList.add(assoc.getPaObject());
        	       }
        	       customObject.setpaObjectList(paObjectList);
            	if (property1Flag) {
            		customObject.setProperty1Object(item.getProperty1Object());
            	}
            	if (property2Flag) {
            		customObject.setProperty2Object(item.getProperty2Objects());
            	}
            	if (property3Flag) {
            		customObject.setProperty3Object(item.getProperty3Object());
            	}
            	if (property4Flag) {
            		customObject.setProperty4Object(new DataConverter().toProperty4Object(item));
            	}
     
            	return customObject;
            }
    Je résume: quand l'étape STEP2 est exécutée, ma requête objectif passe sans problème.

  6. #6
    Membre très actif

    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    485
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 485
    Billets dans le blog
    5
    Par défaut
    C'est simple, je n'ai rien compris!

    Bon, que dire?

    Déjà, Hibernate a été spécifié au JCP, c'est devenu JPA. Il est plutôt recommandé d'utiliser JPA que Hibernate.
    Et il est plutôt recommandé d'utilisé les annotations que les fichiers XML (Si il y en a).
    Effectivement, on ne fait plus de XML depuis 10 ans.

    On parle de classe ItemObject, elle est où cette classe?
    Comment est fait son mapping? où sont les annotations? Le XML (à ne pas utiliser)?

    Pour résumer, JPA/Hibernate est un ORM.

    Ce framework permet de faire un mapping entre une BDD relationnelle (table, colonne...) et le modèle métier qui lui est objet (classe, héritage...).

    Même si c'est compliqué, JPA/Hibernate gère l'héritage ( https://viseo.developpez.com/tutorie...gies-heritage/ )

    Dans un premier temps, il est recommandé d'avoir un UML compréhensible (Rien que là dessus, j'ai déjà lâché l'affaire).

    Ensuite, on fait un mapping avec la BDD.
    Même si on le faisait il y a 10 ans avec du XML (c'est d'ailleurs encore possible), on le fait aujourd'hui par les annotations JPA


    Une fois ces deux étapes faites, Hibernate/JPA s'occupe de tout:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public List<ItemObject> getByDate(Date dateBegin, Date dateEnd){
     
         Query query = em.createQuery("select item from ItemObject item where (item.ins between :dateBegin and :dateEnd) or (item.mod between :dateBegin and :dateEnd)");
         query.setParameter("dateBegin",dateBegin);
         query.setParameter("dateEnd",dateEnd);
         return query.getResultList()
    }
    Et c'est tout, ça suffit.

    On utilise EntityManager:
    https://www.baeldung.com/hibernate-entitymanager

    https://docs.oracle.com/javaee/7/api...tyManager.html

    Les problèmes de performance, ça vient après (notamment en choisissant intelligemment les EAGER et LAZY).

Discussions similaires

  1. Interprétation des requètes générées par hibernate
    Par pmboutteau dans le forum Hibernate
    Réponses: 2
    Dernier message: 11/02/2015, 09h19
  2. Réponses: 2
    Dernier message: 02/02/2011, 11h14
  3. StatMan dans les requètes générées par EF4?
    Par michelatoutfox dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 14/10/2010, 10h49
  4. Réponses: 6
    Dernier message: 22/05/2008, 11h59
  5. propriete générée par hibernate
    Par piedsvelus dans le forum Hibernate
    Réponses: 1
    Dernier message: 15/07/2007, 00h13

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