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 :

Mapping One to Many


Sujet :

Hibernate Java

  1. #1
    Membre averti
    Inscrit en
    Décembre 2004
    Messages
    54
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 54
    Par défaut Mapping One to Many
    Bonjour à tous !

    Je me mets depuis peu à hibernate et je suis confronté à un problème qui me rend chèvre.

    Donc j'ai une classe entité commande qui doit avoir une relation oneToMany unidirectionnelle avec une autre classe entité nommée produit.

    Voici le code de la jointure dans la classe commande :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    List<Produit> produits = new ArrayList<Produit>();
    	@OneToMany(cascade={CascadeType.ALL})
    	@JoinTable(
    			name="produitsCommande",
    			joinColumns=@JoinColumn(name="produit_id",unique=false),
    			inverseJoinColumns=@JoinColumn(name="idCommande",unique=false)
    	)
    	public List<Produit> getProduits() { return this.produits; }
    	public void setProduits(List<Produit> prods) { this.produits = prods; }
    Je n'ai pas d'erreur d'execution lorsque je compile et execute les créations de tables (j'utilise Maven).
    Seulement lorsque je lance des tests unitaires en créant deux produits, et que je lance mon test unitaire de création de commande avec comme liste de produits les 2 produits créés précédemment, je me retrouve avec une table de jointure comme ceci :
    +------------+------------+
    | produit_id | idCommande |
    +------------+------------+
    | 1 | 1 |
    | 1 | 2 |
    +------------+------------+

    Ce qui n'est absolument pas logique, l'inverse devrait être fait, avec deux idCommande à 1 (l'id en lui même) et les produit_id devraient être à 1 et 2.
    Si je me débrouille pour paramétrer l'inverse, alors la contrainte d'unicité sur idCommande m'empêche d'enregistrer la commande avec une erreur du style "Duplicate entry '1' for key 1"...

    Ma question finalement est : comment paramétrer simplement une relation oneToManu unidirectionnelle ?

    D'avance merci.

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2004
    Messages : 46
    Par défaut
    je n'ai jamais utilisé hibernate et les annotations mais une chose est sure : il ne doit pas y avoir de contrainte d'unicitté sur la colonne idCommande de ta table produitsCommande.

    si tu veux une clef primaire il faut :
    - soit qu'elle porte sur les deux colonnes
    - soit creer une 3eme colonne qui sera une clef primaire technique

    je ne sais pas si cela vaut vraiment le coup de mettre ce genre de contrainte sur cette table

  3. #3
    Membre averti
    Inscrit en
    Décembre 2004
    Messages
    54
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 54
    Par défaut
    Merci pour ta réponse,

    C'est à dire que justement je ne sais pas contrôler avec hibernate la création des clé primaires dans ce cas, hibernate la génère automatiquement...
    En fait j'ai déjà pensé à ajouter une 3ème colonne qui aurait la fonction d'être la clé primaire mais je n'ai trouvé aucune docs sur le sujet...

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    N'aurais tu pas plutôt besoin d'une relation many-to-many, puisque tu utilises une table de jointure ?

  5. #5
    Membre averti
    Inscrit en
    Décembre 2004
    Messages
    54
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 54
    Par défaut
    Citation Envoyé par fr1man Voir le message
    N'aurais tu pas plutôt besoin d'une relation many-to-many, puisque tu utilises une table de jointure ?
    Non je ne pense pas vu qu'un produit présent dans la table produit ne doit pas avoir de référence avec une commande.
    La commande ne fait que piocher dans des produits disponibles et référencés...
    Donc relation oneToMany unidirectionnelle.

    A la limite je pourrais faire appel à une collection d'éléments (@CollectionOfElements) mais je tombe sur le même problème que ci-dessus...

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    C'est pourtant bien ce que tu essaies d'implementer.
    Une commande contient n produits.
    Un produit peut appartenir a n commandes.
    Donc relation many-to-many unidirectionnelle et le tour est joué.
    A moins que tu aies besoin d'autres informations dans cette table de jointure.

  7. #7
    Membre averti
    Inscrit en
    Décembre 2004
    Messages
    54
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 54
    Par défaut
    Citation Envoyé par fr1man Voir le message
    C'est pourtant bien ce que tu essaies d'implementer.
    Une commande contient n produits.
    Un produit peut appartenir a n commandes.
    Donc relation many-to-many unidirectionnelle et le tour est joué.
    A moins que tu aies besoin d'autres informations dans cette table de jointure.
    Merci à toi fr1man, effectivement après avoir adapté mon code pour une relation ManyToMany, j'arrive bien au résultat attendu, et je n'ai plus d'erreurs concernant des violations de contraintes d'unicités !



    Voici mon code remanié pour ceux que ça intéresse :

    Dans la classe commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    private List<Produit> produits = new ArrayList<Produit>();
    	@ManyToMany(cascade={CascadeType.ALL}, targetEntity=Produit.class)
    	@JoinTable(
    			name="produitsCommande",
    			joinColumns=@JoinColumn(name="idCommande",unique=false),
    			inverseJoinColumns=@JoinColumn(name="produit_id",unique=false)
    	)
    	public List<Produit> getProduits() { return this.produits; }
    	public void setProduits(List<Produit> prods) { this.produits = prods; }
    et dans la classe produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    private List<Commande> commandes = new ArrayList<Commande>();
    	@ManyToMany(
    			cascade={CascadeType.ALL},
    			mappedBy="produits",
    			targetEntity=Commande.class
    	)
    	public List<Commande> getCommandes() { return commandes; }
    	public void setCommandes(List<Commande> comms) { this.commandes = comms; }
    Voilà, merci encore !

  8. #8
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Citation Envoyé par Ethylene Voir le message
    Merci à toi fr1man, effectivement après avoir adapté mon code pour une relation ManyToMany, j'arrive bien au résultat attendu, et je n'ai plus d'erreurs concernant des violations de contraintes d'unicités !
    Effectivement ça marche, mais je ne suis pas certain que la conception soit judicieuse, à moins que ce soit juste pour apprendre à utiliser Hibernate. La table Produit ne devrait pas avoir de référence sur les commandes en tant que tel. D'ailleurs tu le dis toi-même.
    Citation Envoyé par Ethylene Voir le message
    Non je ne pense pas vu qu'un produit présent dans la table produit ne doit pas avoir de référence avec une commande.
    La commande ne fait que piocher dans des produits disponibles et référencés...
    Donc relation oneToMany unidirectionnelle.

    A la limite je pourrais faire appel à une collection d'éléments (@CollectionOfElements) mais je tombe sur le même problème que ci-dessus...
    La relation Commande <-> Produit étant un classique du genre, la meilleure solution que je sache c'est d'introduire une table intetrmédiaire "LineItem" correspondant à chaque produit commandé. Commande va contenir une collection de LineItem, et chaque LineItem aura une relation many-to-one avec un Produit. Ceci te permet d'ajouter des champs "quantite" et "prixUnitaire" dans LineItem correspondant à la quantité commandée et au prix pour chaque produit. Une LineItem étant fortement liée à une Commande, tu pourrais même utiliser une collection d'éléments (@CollectionOfElements).
    Comme code on pourrait avoir :
    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
     
    public class Command implements Serializable {
     
           @org.hibernate.annotations.CollectionOfElements
           @JoinTable(...)
           @org.hibernate.annotations.IndexColumn(...)
           private List<LineItem> lineItems;
    ...
    }
     
    public class LineItem implements Serializable {
          private int quantity;
     
          @Many-to-One
           private Produit produit;
    }
    Et "Produit" n'aurait de référence ni sur Command, ni sur LineItem, sauf si vraiment ton modèle le nécessite, mais à mon avis ce n'est pas nécessaire.
    Voilà, c'est ce que je vois de mieux pour ce genre de relations, j'espère que ça corresponde à ce que tu voulais au départ.
    @+

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    @manblaizo
    Tu as effectivement raison s'il veut ajouter des données dans sa table de jointure, sinon, je ne vois pas bien le problème de conception.
    Produit n'est pas lié directement à Commande, c'est la table de jointure qui fait le lien.

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Par défaut
    Citation Envoyé par fr1man Voir le message
    @manblaizo
    Tu as effectivement raison s'il veut ajouter des données dans sa table de jointure, sinon, je ne vois pas bien le problème de conception.
    Produit n'est pas lié directement à Commande, c'est la table de jointure qui fait le lien.
    Oui, en tout cas d'après le code qu'il a donné à la fin, on voit que Produit contient une collection de Commande, ce qui résout son problème, mais si j'ai bien compris, ça ne correspond pas tout à fait à ce qu'il cherchait à faire au départ. La solution serait bien sûr d'ajouter une table intermédiaire avec ou sans données supplémentaires (mais en général on peut toujours trouver des données à ajouter dans la table de jointure ). Mais bien évidemment, tu as raison, c'est une relation Many-to-Many qui est scindée en deux relations Many-to-one en ajoutant une entité de jointure, et Produit n'a pas besoin de référence sur Commande.

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

Discussions similaires

  1. Insertion de données avec un mapping one-to-many
    Par mj_51 dans le forum Hibernate
    Réponses: 2
    Dernier message: 26/06/2014, 13h39
  2. [Mapping] Erreur lors du mapping one-to-many
    Par nifertari18 dans le forum Hibernate
    Réponses: 2
    Dernier message: 21/05/2013, 21h15
  3. Mapping one-to-many - saveOrUpdate
    Par -=mateo=- dans le forum Hibernate
    Réponses: 4
    Dernier message: 15/07/2010, 17h36
  4. Réponses: 2
    Dernier message: 17/07/2006, 14h45
  5. [Hibernate] Mapping one-to-many + cle composite
    Par brainstorm dans le forum Hibernate
    Réponses: 2
    Dernier message: 23/06/2006, 10h51

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