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

JSF Java Discussion :

Comment simplifier les beans Hibernate


Sujet :

JSF Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut Comment simplifier les beans Hibernate
    Bonjour, je connais les bases d'hibernates mais je me pose une question sur certains points, comme celle-ci :

    Prenons une table Vehicule qui possede une cle etrangere vers une table Marque qui possede (en plus de la key), le nom de la marque.
    Hibernate me traduit cela en creant une classe Marque, et en typant l'attribut marque du vehicule avec Marque.

    Ce comportement est tres interessant dans certains cas, mais dans celui-ci, j'aimerai qu'il me prenne directement la String et qu'il la mette dans l'attribut marque car pour pouvoir y l'afficher je dois faire ca : #{vehicule.marque.nomMarque}, et ceci ne fonctionne pas toujours a cause du lazy loading ou si marque est nul.

    Quel est le meilleur moyen de reagir face a ce cas ? Changer le hbm, la classe, laisser comme cela ?
    Merci pour vos reponses !

  2. #2
    Membre éclairé
    Inscrit en
    Novembre 2007
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 69
    Par défaut
    Salut!

    Concernant le problème, que la marque peut être null, n'a aucune relation avec hibernate c'est votre logique donc tu doit tester si la marque null ou non.

    Et si la marque est obligatoire et ne peut pas être null, là tu dois dire à hibernate de vérifier s'il est null avant de sauvegarder l'objet vehicule dans la base de données.

    Et concernant le problème da lazy, tu as deux solutions:

    1-D'inialiser la relation vehicule ---> marque avant de fermer la session hibernate en utilisant le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Hibernate.initialize(vehicule.getMarque());
    ou tout simplement:


    Où vehicule c'est l'instance de type Vehicule à utiliser dans tes managedBean.

    2- D'utiliser le design pattern session view filter, qui repose sur le principe d'ouvrir une session hibernate pour chaque requete utilisateur et la fermer dans la fin du traitement de la requete, mais il faut l'utiliser seulment si tu te sens bloqué.

    Merci.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut
    Merci de ta reponse, c'est en effet le seul moyen que je vois pour le moment, utiliser le getter pour "remplir" la marque. Mais je trouvais ca justement assez moche et ma question se dirigeait plutot sur la possibilite de "bypasser" la classe et de mettre directement la string marque dans la classe Vehicule (au moment du mapping), si tu vois ce que je veux dire...

  4. #4
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Bonjour
    Je ne vois vraiment pas en quoi #{voiture.marque.nom} te gène: moi je trouve ça très élégant au contraire.

    Sinon, tu as du rater la seconde moitié de la réponse de lion.maroc: tu peux éviter le problème du lazy fetch en passant par une solution comme OpenSessionInView (via un filtre en général). Le mieux sera d'utiliser Spring.

    Bonne chance.

  5. #5
    Membre éclairé
    Inscrit en
    Novembre 2007
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 69
    Par défaut
    D'abord a mon opion tu dois respecter les notions de l'oriente objet, dans les proprités de la marque doivent etre dans la classe marque.

    Et pour faire le mapping du nom de la marque dans l'objet vehicule je sais pas si hibernate de te donner cette possibilité, tu peux seulment mapper la clé etrangère car il existe dans la table vehicule.

  6. #6
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Autre possibilité: Tu peux envisager d'utiliser un Object Assembler qui fait le mapping depuis les objets persistants vers d'autres objets plus adaptés à l'IHM.
    Y'a dozer par exemple qui fait ça (merci Angelo )

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut
    Merci pour vos reponses, je vais donc rester avec la premiere solution...
    Je trouvais ca un peu long mais vous avez raison, il vaut mieux garder la structure telle qu'elle est...

    Bonne journee !

  8. #8
    Membre éclairé
    Inscrit en
    Novembre 2007
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 69
    Par défaut
    Oui c'est une bonne idée d'utiliser le design pattern Value object ou data transfer object, pour créer un autre objet qui prend la forme da la vue et de le populer à partir des autres objets, vraiment j apprecie bcp ce design pattern.

    Mais "dozer" travaille avec la reflexion pour faire le mapping object to object qui va alourdir un peu l'application.

    Tu peux le faire manuelement si tu peux, c'est mieux a mon avis.

    et en plus tu dois le faire dans les deux sens de la base vers la vue et de la vue vers la base.

    Merci.

  9. #9
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Citation Envoyé par lion.maroc Voir le message
    Mais "dozer" travaille avec la reflexion pour faire le mapping object to object qui va alourdir un peu l'application.

    Tu peux le faire manuelement si tu peux, c'est mieux a mon avis.

    et en plus tu dois le faire dans les deux sens de la base vers la vue et de la vue vers la base.
    Ouep, peut être, mais ça risque de ne pas être drôle du tout à coup de 5 ou 10 entités par exemple avec quelques champs et une profondeur qui dépasse le 1 ou 2 niveaux ...

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut
    Oui je ne pensais qu'a une modification du hbm au debut, pas de modifications manuelles qui ne seront pas comprises par la suite :p

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut
    J'ai garde donc la structure avec une classe Marque..
    Quel est le bon moyen pour ajouter ou modifier la classe vehicule maintenant ?

    Lorsque l'utilisateur arrive a un formulaire d'ajout, j'aimerai faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <tr>
    	<td><h:outputText>Marque : </h:outputText></td>
    	<td><h:selectOneMenu value="#{vehicule.marque.nomMarque}">
    	     <f:selectItems value="#{vehb.listMarque}" />
    	</h:selectOneMenu></td>
    </tr>
    Mais bien entendu marque est nul a ce moment..
    De plus, la classe marque possede maintenant une collection de vehicule (tous les vehicules qui sont de cette marque), donc si je veux faire une modification de la base, je dois charger cette collection...

    Quel est le meilleur moyen de proceder, a part celui qui consiste a creer un bean request qui garde le nom et qui va chercher la collection de vehicules (qui sera enorme) pour la mettre dans le champs marque au moment de l'ajout.. ?

    Merci d'avance

  12. #12
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Bonjour
    Citation Envoyé par Dr@ke Voir le message
    Mais bien entendu marque est nul a ce moment..
    Pourquoi ??
    Citation Envoyé par Dr@ke Voir le message
    De plus, la classe marque possede maintenant une collection de vehicule (tous les vehicules qui sont de cette marque), donc si je veux faire une modification de la base, je dois charger cette collection...
    quelle base ? Où est le problème ? pas comprendre moi
    Citation Envoyé par Dr@ke Voir le message
    Quel est le meilleur moyen de proceder, a part celui qui consiste a creer un bean request qui garde le nom et qui va chercher la collection de vehicules (qui sera enorme) pour la mettre dans le champs marque au moment de l'ajout.. ?
    Encore pas comprendre ...

    Veux tu reformuler s'il te plaît en posant clairement les problèmes ?


  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut
    Desole j'explique mal

    J'ai un bean Vehicule (en scope session), qui a un attribut marque de type Marque. Marque est une classe avec un id, et une string (nom de la marque).

    Hibernate m'a crée Marque de cette facon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private int idMarque;
    private String nomMarque;
    private Set<Vehicule> vehicules = new HashSet<Vehicule>(0);
    Lorsque j'affiche un vehicule existant, j'accede a marque de cette facon : #{vehicule.marque.nomMarque}

    Maintenant lors de la creation d'un vehicule (ou de la modification), j'ai un formulaire dans lequel l'utilisateur peut choisir une des marques dans une liste deroulant.
    Instinctivement, j'ai formulé ce formulaire de cette facon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <h:selectOneMenu value="#{vehicule.marque.nomMarque}">
        <f:selectItems value="#{vehb.listMarque}" />
    </h:selectOneMenu>
    Mais a ce moment, marque est null. Voila l'erreur affichee lors de la validation du formulaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    value="#{vehicule.marque.nomMarque}": Target Unreachable, 'marque' returned null
    De plus, meme si j'arrive a mettre a jour le nomMarque, l'important est de mettre a jour id_marque, car c'est l'id qui est la cle etrangere.

    Je ne sais donc pas comment faire : Dois-je recuperer la string, et modifier a la main l'id_marque, dois-je charger la classe Marque depuis la base de donnees en fonction du nom passe par l'utilisateur et la mettre dans vehicule.marque a la main, ou y a-t'il une solution simple que je m'obstine a ne pas voir ?

    Desole si ces questions semblent stupides et merci pour le temps accordé !

  14. #14
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Oki, je comprends mieux, merci

    Pour la création de véhicule, tu dois te mettre dans l'esprit que le but n'est pas de remplir le champ vehicule.marque.nomMarque comme tu essaies de faire, mais plutôt de récupérer une instance de type marque déjà existante dans la BD pour ensuite faire l'association entre les deux.

    Donc, je te propose d'ajouter un champ id_marque à ton managed bean, et faire pointer ton selectOneMenu la dessus.
    les éléments du selectOneMenu sont alors les couples (label=marque.nom, value=marque.id)

    Après validation, tu récupères la marque sélectionné avec un appel du genre findMarqueById(id_marque) et tu l'associes à ton véhicule nouvellement crée, vehicule.setMarque(marque) et hop !

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut
    Voila, c'est ce qu'il me semblait (et ce que j'essayai d'expliquer plus haut hahah) mais justement cette technique me fait peur du fait que Marque possede une collection de vehicule
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private Set<Vehicule> vehicules = new HashSet<Vehicule>(0);
    et que lorsque je vais la recuperer avec findMarqueById(id_marque), cela va me charger tous les vehicules de cette marque. C'est bien ce que Hibernate va faire ?
    C'est a dire, si j'ai 100 000 peugeot, il va me charger un tableau de 100 000 vehicules a chaque fois ?

    Enfin, pourquoi la marque est null ? Il ne peut pas l'initialiser comme un grand ?

  16. #16
    Expert confirmé
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Par défaut
    Non, par défaut les collections sont en mode lazy dans Hibernate, dans pas de risque. A moins bien sur que tu as manuelelement spécifié lazy-false dans ton fichier .hbm ?

  17. #17
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 91
    Par défaut
    Pour une fois, j'accueille le lazy a bras ouvert
    Il est bien actif et l'ajout se passe sans probleme...

    Merci une nouvelle fois djo.mos !

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

Discussions similaires

  1. Comment empécher Excel de simplifier les fractions
    Par romanticide dans le forum Excel
    Réponses: 7
    Dernier message: 06/02/2009, 15h35
  2. Réponses: 7
    Dernier message: 14/05/2008, 18h31
  3. Réponses: 9
    Dernier message: 02/08/2007, 17h08
  4. Réponses: 4
    Dernier message: 09/05/2007, 10h21
  5. [Hibernate] Comment ramener les valeurs des tables de ref ?
    Par PamelaGeek dans le forum Hibernate
    Réponses: 9
    Dernier message: 07/02/2006, 23h52

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