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 :

Question pour une requête sur plusieurs tables/objets


Sujet :

Hibernate Java

  1. #21
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Non !
    Une requête HQL != une requête SQL !

    Ici, je fais un "SELECT p FROM Personne p (...)" en HQL
    --> Il me fait donc une requête SQL pour récupérer les Personnes dans la base.
    Ok !

    Mais l'objet Personne contient une liste d'événements.
    Là, Hibernate me génère donc une autre requête pour construire cette liste et récupérer dans la base les événements auxquels participent la Personne ...


    Moi je voudrais récupérer un objet de type Personne qui ne soit pas le "vrai" reflet des données présentes dans la base puisque je ne veux pas avoir tous les événements pour une personne ni tous les animateurs pour un événement !!

  2. #22
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    as-tu bien mi lazy="true" sur tes association? Sinon, au dela de la requet HQL, hibernate va aussi, après, "remplir" tes personnes avant de te les rendre. Si t'as bien mis le lazy sur tes associations, hibernate ne rempliara pas tes collection mais remplira tes personne avec les données issues du select uniquement.


    Si t'as toujours des soucis avec ca, envoie le mapping ainsi que la requete hql utilisée et les requetes sql affichées par hibernate.

  3. #23
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Je crois que ça fonctionne !

    J'ai donc mis lazy="true" pour mes associations.

    Et puis j'ai modifié ma requête qui est de la forme suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT p  From Personne AS p  left join fetch p.evenements AS e  left join fetch e.animateurs a WHERE a.idAnim =:animId
    Je vais faire encore quelques tests mais je pense être sur la bonne voie ...

    Merci pour tout, tchize !

  4. #24
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Comme je le pensais, c'était trop beau !

    Quand je fais ma première recherche, ça fonctionne.

    Mais si je fais une recherche différente juste derrière, je récupère le résultat de la première recherche ...

  5. #25
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    fait voir ton code pour les deux recheche (du début à la fin). Y a pas de raison.

  6. #26
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Voilà ma requête !
    Citation Envoyé par pontus21 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT p  From Personne AS p  left join fetch p.evenements AS e  left join fetch e.animateurs a WHERE a.idAnim =:animId

  7. #27
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    on peux voir le code en entier depuis la création de session jusque sa fermeture?

  8. #28
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Session session = HibernateUtil.currentSession();
    String requete = "SELECT p  From Personne AS p  left join fetch p.evenements AS e  left join fetch e.animateurs a WHERE a.idAnim = '" + id_anim + "'";
    Query query = session.createQuery(requete);
    ArrayList<Personne> personnes = (ArrayList<Personne>)query.list();
    La classe HibernateUtil :
    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
     
    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
     
    public class HibernateUtil {
    	private static final SessionFactory sessionFactory;
     
    	static {
    		try {
    			// Créé la SessionFactory
    			sessionFactory = new Configuration().configure().buildSessionFactory();
    		} catch (HibernateException ex) {
    			throw new RuntimeException("Problème de configuration : " + ex.getMessage(), ex);
    		}
    	}
     
    	public static final ThreadLocal session = new ThreadLocal();
     
    	public static Session currentSession() throws HibernateException {
    		Session s = (Session) session.get();
    		// Ouvre une nouvelle Session, si ce Thread n'en a aucune
    		if (s == null) {
    			s = sessionFactory.openSession();
    			session.set(s);
    		}
    		return s;
    	}
     
    	public static void closeSession() throws HibernateException {
    		Session s = (Session) session.get();
    		session.set(null);
    		if (s != null)
    			s.close();
    	}
    }

  9. #29
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    je peux voir l'entièreté des deux appel (voir comment tu passe le anim, etc), parce que à voir ton code, de fait, si tu l'exécute deux fois avec le meme id, t'auras deux fois la meme réponse, ca me semble assez logique.

  10. #30
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Oui, mais je le passes avec des id différents !
    C'est bien là le problème !

  11. #31
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    comme je disais, tout le code englobant, là je vois un bout de code de 4 lignes complètement hors contexte

  12. #32
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    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
    public class AnimateurDaoImpl extends HibernateDaoSupport implements AnimateurDao {
    private final Log logger = LogFactory.getLog(AnimateurDaoImpl.class);
     
    @SuppressWarnings("unchecked")
    public List<Personnes> recherchePersonnesPourAnimateur(Integer idAnim){
    	logger.info("recherchePersonnesPourAnimateur pour le id anim : " + idAnim);
    	Session session = HibernateUtil.currentSession();
     
    	String requete = "SELECT p  From Personne AS p  left join fetch p.evenements AS e  left join fetch e.animateurs a WHERE a.idAnim = '" + idAnim + "'";
     
    	Query query = session.createQuery(requete);
     
    	ArrayList<Personne> personnes = (ArrayList<Personne>)query.list();
    	return clients;
    }
    Et mon contrôleur :
    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
    public class RechercheUnitaireController extends SimpleFormController {
    	private Log logger = LogFactory.getLog(RechercheUnitaire.class);
    	private DomainService domainService;
     
    	public void setDomainService(DomainService domainService) {
    		this.domainService = domainService;
    	}
     
    	protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
    		ModelAndView mav = new ModelAndView("/secure/resultat-recherche-unitaire");
    		List<Personne> personnes = null;
    		// On récupère les critères de recherche
    		RechercheUnitaire ru = (RechercheUnitaire)command;
    		personnes = domainService.recherchePersonnesPourAnimateur(ru.getAnimId());
    		mav.addObject("personnes", personnes);
    		return mav;
    	}
     
    	protected Object formBackingObject(HttpServletRequest request) throws Exception {
    		return new RechercheUnitaire();
    	}
    }
    Vraiment, je ne vois aucune raison ...

    Je pense comprendre le problème mais je ne vois pas comment le résoudre.

    La requête est effectuée à chaque fois avec le bon animId (celui correspondant à chaque recherche, donc pas toujours le même) mais le soucis, c'est que pour récupérer les infos de la personne et de l'événement, Hibernate effectue d'autres requêtes la première fois.
    Et comme la seconde requête retourne la même personne (puisque le select porte sur la personne), il ne va pas rechercher les autres infos (qu'il doit avoir stocké dans des objets).

  13. #33
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Citation Envoyé par pontus21 Voir le message
    La requête est effectuée à chaque fois avec le bon animId (celui correspondant à chaque recherche, donc pas toujours le même) mais le soucis, c'est que pour récupérer les infos de la personne et de l'événement, Hibernate effectue d'autres requêtes la première fois.
    Et comme la seconde requête retourne la même personne (puisque le select porte sur la personne), il ne va pas rechercher les autres infos (qu'il doit avoir stocké dans des objets).
    donc si je suis bien
    tu fais deux requete avec des animId différents.
    Ces requetes doivent sortir de la base de données les même personnes
    et tu te plaint que hibernate ne fait pas une deuxième fois un select sur ces personnes ? Y a pas de raison qu'il le fasse puisqu'il connait déjà ces personne. Si dans la même session hibernate tu récupère deux fois un objet Personne avec la même clé, la deuxième fois hibernate ne fera pas de select puisqu'il a déjà cet objet.

    Peut etre nous mettre les id que tu utilise, ce que hibernate sort à chaque fois et ce que tu aurais voulu qu'il sorte, pour que ce soit plus clair à comprendre

  14. #34
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Oui, ma requête va me retourner la même personne, mais justement, j'aimerais bien qu'il la recharge pour recharger la bonne liste d'événements et d'animateurs.

    Là, que je fais ma recherche avec l'idAnim = 1, il me renvoit la personne 111 avec l'événement 11 qui a pour anim le 1.
    Jusque là, c'est ok.

    Par contre, si juste derrière je fais ma recherche avec l'idAnim = 2, il me renvoit la même personne 111 avec toujours l'événement 11 qui a pour anim le 1.
    Et normalement, il devrait (c'est ce que je voudrais) me renvoyé la même personne 111 mais avec l'événement 22 qui a pour anim 2.

    C'est plus clair comme ça ?

  15. #35
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    normalement, si ton mapping est bien fait, il devrait faire ça:

    avec l'idAnim = 1, il renvoie la personne 111 avec les événements 11 et 22 qui ont respectivement pour anim 1 et 2

    avec l'idAnim = 2, il renvoie la personne 111 avec les événements 11 et 22 qui ont respectivement pour anim 1 et 2

    Tu peux montre le code que tu utilise pour afficher les évènements?

  16. #36
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Ce que tu dis est ce que j'obtenais au début et ce que je ne voulais pas.

    Je veux vraiment obtenir une liste des personnes mais pour ces personnes, je voudrais qu'il ne garde que les événements ayant pour animateur celui passé en paramètre.

    J'ai bien peur que je demande quelque chose de trop compliqué à Hibernate ...

    Existe-t-il un moyen pour forcer Hibernate à recharger un objet ?


    Mon affichage se fait dans une jsp, rien de plus classique ...

    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
    <ul>
    <c:forEach items="${personnes}" var="p">
    	<li>${p.id} - ${p.nom} - ${p.prenom}</li>
    	<c:if test="${not empty p.evenements}">
    		<ul>
    		<c:forEach items="${p.evenements}" var="e">
    			<li>${e.id} - ${e.libelle}</li>
    			<ul>
    			<c:forEach items="${e.animateurs}" var="a">
    				<li>${a.id} - ${a.nom}</li>
    			</c:forEach>
    			</ul>
    		</c:forEach>
    		</ul>
    	</c:if>
    </c:forEach>
    </ul>

  17. #37
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    non la "Personne" est le reflet de ce qui est dans la base de donnée. Tu peux modifier ta requete hql pour éviter qu'il ne charge inutilement des données dont il n'a pas besoin, mais quand tu explorera la relation one-to-many avec, par exemple personne.getEvenenements().iterator(), hibernate va aller charger son contenu.

    D'ailleurs, le code que tu donne, pour une même Personne (peux importe la requete qui l'a ramenée) devrais toujours donner le même affichage, tant qu'on ne modifie pas la base de données.

    Si tu veux juste un certain nombre de données, alors il va falloir modifier ta requete HQL pour qu'elle returne des propriétés et non des objets et, dans ce cas, tu va obtenir un List<Object[]>, chaque Objet correspondant un une propriété de la requete.

  18. #38
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Je pense que vous avez compris ce que j'aimerais obtenir.

    Est-il de faire cela avec Hibernate ?
    Si oui, pourriez-vous me montrer un exemple ?

  19. #39
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    comme déjà dit, il faut faire des requetes sur les propriétés:


    exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT p.id, p.nom, p.prenom, e.id, e.libelle, a.id, a.nom  From Personne AS p  left join fetch p.evenements AS e  left join fetch e.animateurs a WHERE a.idAnim =:animId
    mais il serait quand même plus propre et peut etre plus performant de plutot changer la manière donc vous affichez les résultats pour vous contenter du fait que Hibernante vous donne une liste de "Personnes" (après vous y choisissez ce que vous voulez afficher).... Ce serait déjà plus propre d'un point de vue séparation vue / modèle!

  20. #40
    Membre régulier
    Profil pro
    Dév FrontEnd
    Inscrit en
    Avril 2005
    Messages
    239
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Dév FrontEnd

    Informations forums :
    Inscription : Avril 2005
    Messages : 239
    Points : 114
    Points
    114
    Par défaut
    Justement, ce que vous me proposez de faire incluerait un traitement du côté de la vue, ce qui baffouerait le principe de l'architecture MVC.

    La vue me permet d'afficher n'importe quel ensemble de données.
    Le contrôleur me permet de récupérer seulement les données nécessaires à l'utilisateur ...

    Et je ne vois pas bien quelle est la différence entre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT p.id, p.nom, p.prenom, e.id, e.libelle, a.id, a.nom  From Personne AS p  left join fetch p.evenements AS e  left join fetch e.animateurs a WHERE a.idAnim =:animId
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "SELECT p  From Personne AS p  left join fetch p.evenements AS e  left join fetch e.animateurs a WHERE a.idAnim = '" + idAnim + "'";

Discussions similaires

  1. Requête sur plusieurs tables/objets
    Par pontus21 dans le forum Hibernate
    Réponses: 2
    Dernier message: 29/04/2009, 14h43
  2. Réponses: 2
    Dernier message: 12/01/2008, 14h57
  3. Aide pour une requête sur deux tables
    Par Andry dans le forum Développement
    Réponses: 2
    Dernier message: 05/11/2007, 07h14
  4. Aide pour une requête sur deux tables
    Par Andry dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/11/2007, 07h14
  5. faire une requête sur plusieurs tables
    Par julien.63 dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 16/08/2006, 22h58

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