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 :

creer un order sur une fonction avec criteria


Sujet :

Hibernate Java

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Points : 12
    Points
    12
    Par défaut creer un order sur une fonction avec criteria
    bonjour,
    je cherche a ordonner une requete par rapport au resultat d'une procedure qui prend en parametre une fonction .

    cela donnerai à peu pres ca en HQL en ne recuperant que l'objet

    from monObjet where ... Order by distance (monObjet.propriete , "100")

    dans le meme esprit

    from monObjet where ... Order by max(monObjet.propriete)

    mais
    avec des criteria

    Order.asc()
    prend en parametre une proprieté, non un fonction

    pouvez vous m'aider ?

  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
    Order.asc( ... ) prend une String qui représente le nom de la propriété sur laquelle va se faire le tri.
    Si ta fonction retourne ce nom, il n'y a pas de problème...

    Je ne comprends pas bien ce que tu cherches à faire, mais ça ne ressemble pas à un tri mais plutôt à un filtre... Peux-tu expliquer ce que renvoie la fonction ?

    A+
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    bonjour,

    oula non, je parle d'une fonction plsql pas d'une fonction java.

    je veux ordonner par rapport a une fonction

    en sql on fait un ORDER BY length(myChaine )
    par exemple , ca marche aussi en HQL mais pas avec des criterias

    Order.asc('length(proto.name)');

    quand je fait ca, il me gueule dessus propriete est une propriete, normal pas une expression

  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
    Citation Envoyé par maouth Voir le message
    en sql on fait un ORDER BY length(myChaine )
    par exemple , ca marche aussi en HQL mais pas avec des criterias
    Tu plaisantes ???
    La clause order by sql est suivie du nom d'une colonne (ou d'une liste de colonnes).
    On peut accessoirement mettre un numéro qui représente la position de la colonne dans la liste du select (ou dans le format de la table si * est utilisée), mais length(myChaine) !!!
    Ça peut fonctionner si cette longueur est comprise entre 1 et le nombre max de champ du select mais c'est tout !
    C'est quand même du grand n'importe quoi je pense... (sans t'offenser)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Tu plaisantes ???
    La clause order by sql est suivie du nom d'une colonne (ou d'une liste de colonnes).
    On peut accessoirement mettre un numéro qui représente la position de la colonne dans la liste du select (ou dans le format de la table si * est utilisée), mais length(myChaine) !!!
    Ça peut fonctionner si cette longueur est comprise entre 1 et le nombre max de champ du select mais c'est tout !
    C'est quand même du grand n'importe quoi je pense... (sans t'offenser)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    select *, length(reference) from tiers order by length(reference) desc ;
       id    |  reference   | length 
    ---------+--------------+--------
     1169792 | ABCDEFGHIKLM |     12
     1169800 | ABCDEF       |      6
    (2 rows)
     
    select *, length(reference) from tiers order by length(reference) asc ;
       id    |  reference   | length 
    ---------+--------------+--------
     1169800 | ABCDEF       |      6
     1169792 | ABCDEFGHIKLM |     12
    (2 rows)
    V(result[i]) : (length(reference) > #[columns]) == true

    12 > 3
    6 > 3

  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
    Oui, dans ce cas "length(reference)" représente bien une colonne de la requête

    D'ailleurs, en faisant un test avec MySQL, je découvre que tu peux également faire (sachant que "n'importe quoi" n'existe pas)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT * FROM T_TEST
    order by length("n'importe quoi")
    et ça ne pose pas de problème...
    Dire sur quoi il tri est une autre histoire par contre...

    Bref, en tout cas, je comprends mieux le besoin initial.
    Il faudra passer soit par un createQuery, soit par un createSQLQuery
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Oui, dans ce cas "length(reference)" représente bien une colonne de la requête

    D'ailleurs, en faisant un test avec MySQL, je découvre que tu peux également faire (sachant que "n'importe quoi" n'existe pas)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT * FROM T_TEST
    order by length("n'importe quoi")
    et ça ne pose pas de problème...
    Dire sur quoi il tri est une autre histoire par contre...

    Bref, en tout cas, je comprends mieux le besoin initial.
    Il faudra passer soit par un createQuery, soit par un createSQLQuery
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    select * from tiers order by length(reference) asc ;
       id    |  reference   
    ---------+--------------
     1169800 | ABCDEF
     1169792 | ABCDEFGHIKLM
    (2 rows)
    le length(reference) dans le select du premier post n'était là que pour montrer qu'il triait correctement…
    il ne doit pas être un membre du select pour que cela fonctionne…

    quant au tri sur max() c'est autre chose : max est une fonction d'aggrégation qui nécessite un GROUP BY
    trier sur max(champ de la table principale du select)
    n'a d'ailleurs pas de sens car ce max est unique pour toute la table (donc il n'y a rien à trier…) par contre si c'est un max(champ d'un table jointe) cela peut avoir un sens mais cela nécessite quand même un GROUP BY…

    le tri sur length("n'importe quoi") : si vous avez effectivement mis des quotes, le "tri" se fait sur la longueur - constante - de la chaîne de caractères "n'importe quoi"… (en principe cela donne le même résultat que le même select sans order by…)

    tri sur length(n_importe_quoi) génère une erreur si n_importe_quoi n'est pas le nom d'une colonne du select…

    maintenant si vous utilisez JPA, un tri sur un champ @Formula fonctionne…

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    @Entity
    public class MyEntity {@Column(name="name_of_sql_column")
    protected String fieldName ;
     
    @Formula("( LENGTH(name_of_sql_column) )")
    protected int lengthOfColumn ;
    …
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Criteria criteria = getHibernateSession().createCriteria("MyEntity") ;
     
    criteria.addOrder( Order.asc("lengthOfColumn") ) ;
    (par hbm, aucune idée… voir la doc…)

  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
    Citation Envoyé par JeitEmgie Voir le message
    le length(reference) dans le select du premier post n'était là que pour montrer qu'il triait correctement…
    il ne doit pas être un membre du select pour que cela fonctionne…
    Ce que je voulais dire, c'est que "reference" fait bien partie de la table, donc length(reference) "en fait partie" indirectement...
    Mais bon, on peut mettre n'importe quoi, ça fonctionne aussi, et là, ça me surprend un peu...
    Ça se passe comme si, dans le cas de l'utilisation d'une fonction, il rajoutait une colonne au résultat de la requête contenant le résultat de la fonction et qu'il triait sur cette colonne... Ceci dit, ça ne va pas m'empêcher de dormir

    Le passage par Formula devrait effectivement régler son problème.
    On aurait également pu (il me semble) utiliser un champ @Transient si l'objet contient déjà les colonnes utiles (à tester)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    merci,

    je vais tenter le formula,

    l'idee etant de mettre un limit en plus, le transient m oblige a remonter tt les elements pour les virers

    parcontre est il possible de ne pas l'instancier dans mon been ?

    pour le max , si ma proprieté est un set ... je pense que ca peux avoir un sens.
    parcontre j'avous je n'avais pas trop reflechie au group by

  10. #10
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Ce que je voulais dire, c'est que "reference" fait bien partie de la table, donc length(reference) "en fait partie" indirectement...
    Mais bon, on peut mettre n'importe quoi, ça fonctionne aussi, et là, ça me surprend un peu...
    je ne sais quelle DB vous utilisez mais on ne peut pas mettre n'importe quoi dans length()… ni avec PostgreSQL, ni avec MySQL, ni avec ORACLE, …
    en SQL, LENGTH accepte une colonne, une chaîne ou une variable et rien d'autre. Il est évident que LENGTH d'une chaîne ou d'une variable a la même valeur pour chaque row du result set donc ça ne sert pas à grand chose…

    Citation Envoyé par OButterlin Voir le message
    Ça se passe comme si, dans le cas de l'utilisation d'une fonction, il rajoutait une colonne au résultat de la requête contenant le résultat de la fonction et qu'il triait sur cette colonne... Ceci dit, ça ne va pas m'empêcher de dormir

    Le passage par Formula devrait effectivement régler son problème.
    On aurait également pu (il me semble) utiliser un champ @Transient si l'objet contient déjà les colonnes utiles (à tester)
    ça n'a pas de sens de demander à la DB (server) de trier sur un champ @Transient (client-only by definition)…
    ça ne marchera pas… et vous allez avoir une exception lors de la conversion du query en SQL…

    dans ce cas faites :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Arrays.sort( criteria.list(), myTransientFieldComparator ) ;

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    @JeitEmgie : nimport navoik
    @JeitEmgie : mon probleme pas les acotés

    retour au probleme, le length n'est qu'un exemple

    from monObjet where ... Order by distance (monObjet.propriete , "100")

    distance retourne un int

    le tout traduit en criteria.
    sans mettre d autre propriete dans mon bean.

  12. #12
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    Citation Envoyé par maouth Voir le message
    @JeitEmgie : nimport navoik
    @JeitEmgie : mon probleme pas les acotés

    retour au probleme, le length n'est qu'un exemple

    from monObjet where ... Order by distance (monObjet.propriete , "100")

    distance retourne un int

    le tout traduit en criteria.
    sans mettre d autre propriete dans mon bean.
    Order.asc ou Order.desc prennent en paramètre un nom de propriété du bean.

    donc pour le moment le seul moyen que je vois d'avoir une fonction dans le Order by est via @Formula (ou l'équivalent en hbm) sur un champ.

    donc "sans mettre d autre propriete dans mon bean" est trop restrictif dans ce cas… (mais un @Formula est transient : cela ne change pas le schéma de votre db…)


    reste comme solution : sous-classer Order et implémenter
    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
    throws HibernateException {

    pour faire ce que vous voulez…

    (on peut imaginer un NativeOrder qui prend en argument de son constructor du SQL natif… ce qui rend toSqlString() trivial à écrire…)

    (le group by n'est nécessaire que si la fonction est un aggregate… sum, max, avg, etc. )

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Points : 12
    Points
    12
    Par défaut
    juste pour info, je sais c'est pas propres

    j'ai fait un truc en sql avec restrictionSql
    ( true ORDRE BY distance( en sql la propriete ))

    mais je retiens l'extends de Order
    si j'ai le temps ...

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

Discussions similaires

  1. Vue sur une fonction avec des paramètres
    Par The F0x dans le forum PL/SQL
    Réponses: 1
    Dernier message: 04/04/2012, 17h00
  2. [PostgreSQL] [PostGreSQL] problème sur une fonction avec connexion
    Par roblescriso dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 04/06/2008, 18h03
  3. [FLASH 8] Creer/utiliser/réfléchir sur une bibli de fonction externe !?
    Par Lorenzo77 dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 16/01/2007, 13h35
  4. creer une fonction avec arguments
    Par niglo dans le forum ASP
    Réponses: 3
    Dernier message: 03/06/2005, 08h04
  5. Erreur sur une fonction avec des paramètres
    Par Elois dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 05/05/2004, 21h00

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