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 :

JPQL, OnetoOne et readAll


Sujet :

JPA Java

  1. #1
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 17
    Par défaut JPQL, OnetoOne et readAll
    Bonjour,
    J'ai un petit souci avec JPA (j'utilise jboss donc hibernate) sur une requête de "readAll".

    Je dispose de deux entites une que l'on va appeler (pour l'exemple) "Bus" et une autre que l'on va appeler "Truc".
    Il existe une relation un a un entre un "Bus" et un "Truc". Et un "Bus" peut ne pas avoir d'"Objet" et inversement.
    J'ai donc fait le mapping comme suit (je me limite aux champs utiles):

    Sur mon entite Truc(Qui gère la relation):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     
    @Id
    private int trucId;
     
    private String nom;
     
    @OneToOne
    @JoinColumn(name = "busID", referencedColumnName = "busID", nullable = true)
    private Bus bus;
    Sur mon entite Bus(qui ne gère pas la relation):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    @Id
    private int busID;
     
    @OneToOne(mappedBy="bus")
    private Truc truc;
    on notera qu'avec un OneToOne, le chargement de la dépendance est faite en eager de base.

    Tout ca fonctionne très bien le problème est le suivant:
    Je désire lire tous mes Bus et afficher la description du Truc (pour ceux qui en ont - left outer en sql classique).

    Stupidement, j'ai créer deux requêtes nommées jpql comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    "from Truc"
    et
     
    "from Bus"
    Mais le problème c'est que lors de l'une de ces requêtes, les informations de l'objet lié ne sont pas chargées.

    Et donc quand je parcours ma liste de réponse, a chaque fois que je fais monBus.getTruc().getNom(), hibernate me refais une requête en base.

    Pour faire simple, comment faire pour que les informations de mon objet soit chargées lors de la requête initiale...

    J'espère que j'ai été suffisamment claire.


    Merci d'avance


    Pierre

    ps: y'a 2000 bus et 2000 trucs dans ma base

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Comment fais tu pour savoir qu'à chaque tour de boucle hibernate retourne dans ta base?

  3. #3
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 17
    Par défaut
    Salut,
    Déjà merci de t'intéresser a mon problème, c'est sympa

    Pour répondre a ta question, je regarder les logs sql.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <property name="hibernate.show_sql" value="true" />
    La premiere requete est en gros
    Et les 2000 autres sont un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    select truc.*
        from truc
          left outer join bus
               on truc.BusID = bus.BusID
    where
        truc.busID = ?

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Ah j'ai jamais fais gaffe à la moulinette d'hibernate quand je fais mes getters.
    Essaie ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT b from Bus b join fetch b.truc
    , et refais ton getter voir...

  5. #5
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 17
    Par défaut
    C'est parfais a un très petit détail près (mais la je fais le pinailleur ).

    Je fais un left outer et pas un inner or, il prend par defaut inner lors d'une jointure.
    Donc la requête serait plutôt:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT b from Bus b left outer join fetch b.truc
    Mais sinon c'est parfais merci beaucoup pour ton aide

    En tout cas, je ne connaissais pas le fetch.

    Je vais me documenter plus en avant pour cette chose.

    Merci encore

  6. #6
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Ouais c la bonne, le join fectch c pour un prechargement. à utiliser avec parcimonie .
    Ravi de t'avoir aidé.

  7. #7
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 17
    Par défaut
    Bonjour,
    Merci encore, mais une seconde question vient se greffer..
    En effet, dans ce sens ca fonctionne bien mais dans l'autre sens, ca refait pareil.

    Ma requête est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT t from Truc t left outer join fetch t.bus
    Elle passe bien en base mais quand je parcours ma réponse des trucs et que je demande des infos sur le bus ben des nouvelles requetes sont faites..


    J'avoue ne plus comprendre.


    Pourquoi fetch, doit etre utilise avec parcimonie ?

  8. #8
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Pourquoi fetch, doit etre utilise avec parcimonie ?
    Parceque ca pourrait te tirer toute ta base, imagine que les tables que tu vas precharger dans ton join fetch soit en relation EAGER avec d'autres tables, eh ba lors du chargement, il chargera aussi ces tables, et ainsi récursivement tu pourrais voir monter toute ta base

  9. #9
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 17
    Par défaut
    a ba ui normale
    En faite si je comprends bien le fetch c'est pour dire de prendre en compte l'annotation de chargement eager ou lazy.

    Sinon une idée de pourquoi dans ce sens, il y a de nouveau un requete pour lors de chaque itération ?


    Merci encore pour tes informations.

  10. #10
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    En faite si je comprends bien le fetch c'est pour dire de prendre en compte l'annotation de chargement eager ou lazy
    Le fetch join est utilisé lorsqu'intelligemment dans ton mapping tu as opté pour une politique LAZY, c une façon de rattraper spécifiquement au besoin dans une requete un prechargement, donc en ayant mis un EAGER normalement tu n'as pas besoin de faire recours aux join fetch.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Sinon une idée de pourquoi dans ce sens, il y a de nouveau un requete pour lors de chaque itération ?
    Je crois que ca doit être le fonctionnement mêmed'hibernate, après je peux me tromper .

  11. #11
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    17
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 17
    Par défaut
    Intéressant, ce que tu me dis la.
    Mais le problème c'est que de base (dans les spec JPA) le chargement est en eager...
    Donc de ce que je comprend, je n'aurais pas besoin de rajouter mon fetch.
    Etrange tout ca

    ps: extrait des source de l'annotation @OneToOne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     public abstract javax.persistence.FetchType fetch() default javax.persistence.FetchType.EAGER
    Merci encore pour le temps que tu me consacres.

    ps: étrange le fonctionnement d'hibernate quand même

  12. #12
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Ouais effectivement le mode de chargement c'est EAGER, c'est pourquoi il faut faire gaffe lors du mapping de bien spécifier selon les cardinalités et le besoin le type de fetch qu'on désire.
    D rien pour l'aide.

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

Discussions similaires

  1. JPQL et requetes dynamiques
    Par skyangel dans le forum JPA
    Réponses: 16
    Dernier message: 30/06/2008, 08h31
  2. Syntaxe date JPQL
    Par aloha dans le forum JPA
    Réponses: 5
    Dernier message: 01/01/2008, 21h39
  3. Passer de (@ManyToOne) a @OneToOne
    Par anisj1m dans le forum JPA
    Réponses: 1
    Dernier message: 08/10/2007, 12h11
  4. [Nhibernate] Relation OneToOne
    Par Vercity dans le forum NHibernate
    Réponses: 1
    Dernier message: 12/03/2007, 11h36
  5. MAPPING oneToOne pb au niveau SGBD
    Par grosFab dans le forum Hibernate
    Réponses: 4
    Dernier message: 25/08/2006, 11h17

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