2009-11-19 6 views
1

Je mappe une base de données propriétaire sur Hibernate pour une utilisation avec Spring. Dans ce document, il y a quelques jointables que, pour l'entité A et entité B ont le schéma suivant:Plusieurs ensembles @ManyToMany à partir d'une table de jointure

CREATE TABLE AjoinB (
    idA int not null, 
    idB int not null, 
    groupEnum enum ('groupC', 'groupD', 'groupE'), 
    primary key(idA, idB, groupEnum) 
); 

Comme vous pouvez le voir, cela indique qu'il peut y avoir de multiples relations A-B qui les mettent dans des groupes différents. Je voudrais finir avec la première ligne pour l'entité A et deuxième pour l'entité B, les ensembles suivants

Set<B> BforGroupC, BforGroupD, BforGroupE; 
Set<A> AforGroupC, AforGroupD, AforGroupE; 

Jusqu'à présent, je n'ai réussi à les mettre dans un jeu et ne pas tenir compte de l'attribut de relation groupEnum :

@ManyToMany(targetEntity=B.class, cascade={ CascadeType.PERSIST, CascadeType.MERGE }) 
@JoinTable(name="AjoinB", [email protected](name="idA"), [email protected](name="idB")) 
private Set<B> BforAllGroups; 

et

@ManyToMany(mappedBy = "BforAllGroups", targetEntity = A.class) 
private Set<A> AforAllGroups; 

Comment puis-je faire plusieurs jeux où ils appartiennent soit à GroupC, groupd ou Groupé?

Vive

Nik

+0

Faire quelque chose comme @DiscriminatorColumn (name = "groupEnum", discriminatorType = ENUM) @DiscriminatorValue ("GroupC") sur la jointure serait belle :-) – niklassaers

Répondre

3

Si vous êtes en prenant en compte, ne le faites pas. Les tables ne coûtent pas cher de nos jours ce qui est avec l'économie et tout, donc créez juste un par association; ce sera tellement plus facile.

Si vous êtes lié par une base de données existante et vous ne pouvez pas changer la structure de cette table, je

  1. Considérons la solution de premier skaffman (+1, BTW). En fonction de votre base de données cible, vous pouvez écrire un déclencheur pour vos vues qui insèrent une valeur "discriminante" adéquate.

  2. Si ce qui précède n'est pas possible dans votre base de données, une autre solution consiste à utiliser custom SQL for CRUD operations pour vos collections. Gardez à l'esprit que cela ne fonctionnera pas (par exemple, votre «valeur discriminante» ne sera pas appliquée) pour les requêtes HQL complexes impliquant votre association dans le cadre de la condition. Vous pouvez également mélanger/assortir ceci avec ci-dessus - par ex. utiliser des vues et utiliser SQL personnalisé pour insérer/supprimer.

  3. Si les deux cas ci-dessus échouent, optez pour "association en tant qu'entité séparée" comme suggéré par framer8. Cela va être plutôt moche (puisque nous supposons ici que vous ne pouvez pas changer vos tables) en raison de clés composites et de tout le code étranger.En fait, cela peut être impossible si l'une de vos associations permet des doublons.

+0

Il est étrange qu'une chose aussi simple que les propriétés sur une relation est si difficile avec Hibernate, donc j'ai déposé un bug sur elle. Le travail que je vais faire est un mélange de # 1 et # 2 dans votre réponse. Merci beaucoup pour votre contribution :-) – niklassaers

3

A ma connaissance, ne peut pas utiliser une telle colonne « discriminateur » de la manière que vous voulez. Hibernate nécessite une table de jointure pour chacun d'entre eux.

Peut-être que vous pourriez être en mesure de définir des vues supplémentaires sur la table, en montrant chacun des groupements?

+0

Salut Skaffman, et merci pour votre suggestion. Si je définis les vues "CREATE VIEW viewAjoinBgroupC AS SELECT idA, idB FROM AjoinB WHERE groupEnum = 'groupC'", alors tout insert dans mon ensemble sera comme "insert into viewAjoinBgroupC VALUES (2,3);", me donnant ainsi un entrée invalide (2,3, 'groupC'). Si vous avez une suggestion sur la façon de surmonter cela, alors c'est une solution de contournement qui pourrait fonctionner. Cheers -Nik – niklassaers

0

Je pense que le conseil quand vous avez besoin d'accéder à un champ dans une table de liens est de faire de la table de liaison un objet et une entité d'hibernation dans son propre droit. A aurait un ensemble d'objets AtoB et AtoB aurait un ensemble d'objets B. J'ai une situation simmilar où la table de lien a un utilisateur associé au lien.

select joinTable.b from A a 
left join a.AtoB joinTable 
where joinTable.group = 'C' 

Il est pas aussi élégant que d'avoir une jointure implicite faite par mise en veille prolongée, mais il vous donne le contrôle dont vous avez besoin.

Questions connexes