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 :

One-to-many, order by et API criteria


Sujet :

Hibernate Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut One-to-many, order by et API criteria
    Bonjour,

    Je suis en train de réfactorer une vieille application de recherche de documents. Pour cela, j'ai repris les fichiers hbm inutilisés jusqu'à présent, la DB qui ne peut pas être modifiée et j'ai décidé d'utiliser l'API criteria.

    La recherche de documents se base sur plusieurs champs stockés dans plusieurs tables de la DB. Pour éviter d'avoir une grosse méthode contenant toute la requête, j'ai découpé cela en utilisant le pattern composite et chaque paramètre de la recherche a une classe qui définit les jointures nécessaires, les restrictions à utiliser, les order by,...

    Cela fonctionne bien sauf pour trier par date l'ensemble des documents par date. Ce tri se fait sur un champs d'une table qui nécessite de deux jointures:

    Document 1 -> * Revision 1 -> * Revision-language.date

    Ma query actuelle ressemble à ceci :
    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
    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
    65
    66
    67
    68
    69
    70
     
    select
            this_.ID as ID23_3_,
            this_.STUDY_NUMBER as STUDY2_23_3_,
            this_.PUBLICATION_TYPE as PUBLICAT3_23_3_,
            this_.EXECUTIVE_SUMMARY as EXECUTIVE5_23_3_,
            this_.AUTHOR as AUTHOR23_3_,
            this_.SUPPLIED_BY as SUPPLIED7_23_3_,
            this_.EDITOR_ID as EDITOR8_23_3_,
            this_.LAST_PUBLICATION_DATE as LAST10_23_3_,
            this_.DATE_MODIFICATION as DATE12_23_3_,
            this_.DATE_INSERTION as DATE13_23_3_,
            this_.USER_MODIFICATION as USER14_23_3_,
            this_.USER_INSERTION as USER15_23_3_,
            this_.OFF_LINE as OFF16_23_3_,
            revisions1_.ID as ID21_0_,
            revisions1_.STUDY_ID as STUDY2_21_0_,
            revisions1_.REVISION_NUMBER as REVISION3_21_0_,
            revisionla2_.ID as ID22_1_,
            revisionla2_.REVISION_ID as REVISION2_22_1_,
            revisionla2_.REVISION_NUMBER as REVISION3_22_1_,
            revisionla2_.LANGUAGE as LANGUAGE22_1_,
            revisionla2_.SOURCE_LANGUAGE as SOURCE5_22_1_,
            revisionla2_.PUBLICATION_DATE as PUBLICAT6_22_1_,
            revisionla2_.TITLE as TITLE22_1_,
            revisionla2_.ABSTRACT_SUMMARY as ABSTRACT9_22_1_,
            revisionla2_.NOTE as NOTE22_1_,
            revisionla2_.NUMBER_OF_PAGES as NUMBER11_22_1_,
            revisionla2_.ISBN_NUMBER as ISBN12_22_1_,
            revisionla2_.FORCE_ARCHIVE as FORCE13_22_1_,
            revisionla2_.DIFFUSION as DIFFUSION22_1_,
            estthemes7_.STU_STUDY_ID as STU1_,
            themes3_.ID as STU2_,
            themes3_.ID as ID25_2_,
            themes3_.CODE as CODE25_2_,
        from
            EST_STUDY this_
        inner join
            EST_REVISION revisions1_
                on this_.ID=revisions1_.STUDY_ID
        inner join
            EST_REVISION_LANGUAGE revisionla2_
                on revisions1_.ID=revisionla2_.REVISION_ID
        inner join
            EST_STUDY_THEME estthemes7_
                on this_.ID=estthemes7_.STU_STUDY_ID
        inner join
            EST_THEME themes3_
                on estthemes7_.STU_THEME_ID=themes3_.ID
        where
            (
                this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or this_.ID=?
                or lower(revisionla2_.TITLE) like ?
                or lower(revisionla2_.ABSTRACT_SUMMARY) like ?
            )
            and (
                this_.OFF_LINE=?
                or this_.OFF_LINE is null
            )
        order by
            revisionla2_.PUBLICATION_DATE desc
    Le résultat de la recherche est correct sauf ce qui concerne le tri par date. Pour l'instant, c'est plus ou moins bien trier. J'ai des dates 2011, 2010, de nouveau 2011, 2009,...

    Auriez-vous une/des idées pour corriger cela ?

    Merci d'avance,

  2. #2
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    J'ai l'impression que cela vient d'un mauvais mapping de mes champs date.

    J'utilise Hibernate avec une DB Oracle 10G.

    Quand j'exécute la query générée par Hibernate en DB sans passer par Hibernate, j'ai le bon résultat, bien trié. Par contre avec Hibernate, il s'emmèle les pinceaux.

    Voici comme j'ai essayé de mapper ma date :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <property name="publicationDate" column="PUBLICATION_DATE" type="timestamp" />
     
    <property name="publicationDate" column="PUBLICATION_DATE" type="date" />
     
    <property name="publicationDate" column="PUBLICATION_DATE" />
    Et dans ma classe, j'utilise java.util.Date.

    Connaitriez-vous problème ?

    Merci d'avance

  3. #3
    Membre Expert
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Par défaut
    Il ne me semble pas que l'API Criteria effectue de tri après le SQL ... Donc si le SQL généré renvoie le bon ordre, la liste sera elle aussi bien ordonnée.
    Deux idées :
    1. Tu passes ensuite par une autre structure, et du coup l'ordre est perdu (par exemple, un set).
    2. Tu n'affiches pas la bonne date dans ton IHM

    Tu pourrais fournir un brin de code, si aucune de ces deux suggestions ne se révèle concluante ?

  4. #4
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    Je passe par un Set car je ne peux pas utiliser les outils de pagination d'Hibernate avec ma query.

    Quand je fais l'order by sur un champs d'une autre table et que je veux éviter les doublons avec la ligne suivante il plante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    executableCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    Donc j'avais trouvé comme solution ceci:

    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
    start = start == -1 ? 0 : start;
    if (lenght == -1) {
    	lenght = Integer.MAX_VALUE;
    }
     
    int nbElements = 0;
    int position = 0;
    Set ignoredObjects = new HashSet();
    while (scrollResults.next() && nbElements < lenght) {
    	session.clear();
    	if (start > position) {
    		if (ignoredObjects.add(scrollResults.get(0))) {
    			position++;
    		}
    	} else if (results.add(scrollResults.get(0))) {
    		nbElements++;
    	}
    }
     
    scrollResults.close();
    Il faudrait utiliser un autre type de collection ?

    EDIT: je suis en train d'essayer en utilisant des instances de LinkedHashSet

  5. #5
    Membre Expert
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Par défaut
    Un Set ne préserve par défaut aucun ordre (par exemple, un HashSet). Effectivement un LinkedHashSet permettra de garder l'ordre d'insertion, ce qui ensuite te permettra de faire une itération dessus en ayant le même ordre que celui qu'avait la liste ...

    Par contre je suis étonné de ce que tu ne puisses pas utiliser DISTINCT_ROOT_ENTITY. Tu peux indiquer le code que tu avais essayé d'utiliser et l'exception obtenue ?

  6. #6
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    J'avais cette exception:

    ORA-01791
    ORA-01791: not a SELECTed expression
    Cause: There is an incorrect ORDER BY item. The query is a SELECT DISTINCT query with an ORDER BY clause. In this context, all ORDER BY items must be constants, SELECT list expressions, or expressions whose operands are constants or SELECT list expressions.
    Action: Remove the inappropriate ORDER BY item from the SELECT list and retry the statement.
    Cela venait de la combinaison entre DISTINCT_ROOT_ENTITY et l'order by avec la propriété venant d'une autre table.

    Puis l'autre problème que j'avais avec DISTINCT_ROOT_ENTITY, si je mettais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    if (start != -1) {
    	executableCriteria.setFirstResult(start);
     }
     if (lenght != -1) {
    	 executableCriteria.setMaxResults(lenght);
    	 executableCriteria.setFetchSize(lenght); // Performance issue
     }
    Il me faisait d'abord le setMaxResult 10 par exemple, puis avec le DISTINCT_ROOT_ENTITY, il me retirait les doublons, donc au final j'avais moins de 10 entrées.

    Cela m'embête un peu ces contournements, ça complexifie la lecture du code,...

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 11/01/2013, 11h16
  2. One-To-Many/many-to-one order by
    Par crofteur dans le forum Persistance des données
    Réponses: 1
    Dernier message: 18/11/2011, 16h56
  3. API Criteria many-to-many
    Par Fennec. dans le forum Hibernate
    Réponses: 6
    Dernier message: 28/06/2010, 15h35
  4. Réponses: 0
    Dernier message: 15/05/2009, 11h48
  5. [Criteria] Relation one-to-many
    Par dedeloux dans le forum Hibernate
    Réponses: 1
    Dernier message: 19/03/2008, 14h00

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