2011-06-10 4 views
3

J'ai besoin d'associer une entité à deux listes d'autres entités - les deux listes contenant des entités du même type. Il ressemble à ceci:Hibernate: plusieurs associations à la même classe

@Entity 
public class Course { 
    private List<Test> preTests; 
    @OneToMany(cascade= javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = “course”) 
    @OrderBy("testNumber") 
    public List<Test> getPreTests() { 
     return preTests; 
    } 

    public void setPreTests(List<Test> preTests) { 
     this. preTests = preTests; 
    } 

    private List<Test> postTests; 
    @OneToMany(cascade= javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = “course”) 
    @OrderBy("testNumber") 
    public List<Test> getPostTests() { 
     return postTests; 
    } 

    public void setPostTests(List<Test> postTests) { 
     this. postTests = postTests; 
    } 
} 

Maintenant, je n'ai pas même pris la peine d'essayer ce en soi, car il semble évident que Hibernate aurait aucun moyen de distinguer ce qui Tests aller dans preTests et qui en postTests. Corrigez-moi si je me trompe, mais les seules informations avec lesquelles il doit travailler sont les clés étrangères dans la table Test pointant vers l'enregistrement Course, et les pré et post-tests pointeront sur le même Course. Ma pensée suivante était de créer explicites PreTest et PostTest sous-classes de Test, et ont un List<PreTest> et un List<PostTest>, mais qui mène à la tristement célèbre « mappedBy référence une propriété d'entité cible inconnue: bien sûr » problème, que les gens de la demande Hibernate - pour des raisons qui me semblent difficiles - est une conception artificielle qui ne risque donc pas de disparaître.

Mon idée actuelle est d'utiliser des tables de jointures distinctes pour contenir les deux associations. Je ne vois pas pourquoi cela ne devrait pas fonctionner. Cela convient aussi à mon désir de garder tout SQL (ou HQL) explicite hors des définitions d'entité, et de résister à la coercition pour créer des clés composites bizarres ou écrire du code reflétant uniquement les bizarreries de mon framework de persistance. Cependant, avant de m'engager dans ce cours, je vous demande si l'un d'entre vous a une solution plus propre ou connaît des failles dans mon raisonnement ici.

Merci d'avance.

Michael

Répondre

1

Je ne sais pas si cela est vraiment une bonne idée ou non, mais vous pouvez inclure un

@org.hibernate.annotations.Where 

annotation sur votre carte d'association et d'utiliser une colonne discriminante sur votre table de test afin que vous pouvez indiquer un pré à partir d'un test Post lors du chargement des instances de test.

+0

Je vous ai donné un upvote parce qu'il est certainement une réponse raisonnable, mais il tombe sous mon désir de garder SQL/HQL réelle de choses, donc je préfère ma solution, même au détriment d'un supplément deux tables et des requêtes légèrement moins efficaces. – Michael

0

Une option est la méthode de mappage d'héritage Table per class hierarchy, dont vous avez l'impression que vous avez commencé à le faire, mais qui n'est pas allée jusqu'au bout.

Une autre option est, comme mentionné autrement, en utilisant le @Where annotation.

Une troisième option, que j'utilise souvent dans des cas similaires, consiste à mapper une seule collection pour tous les tests liés au cours, puis à ajouter des méthodes d'aide pour retourner les sous-ensembles souhaités tests. Exemple de code:

@Entity 
    public class Course { 

    private List<Text> tests; 

    @OneToMany(cascade= javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = “course”) 
    @OrderBy("testNumber") 
    public List<Test> getTests() { 
     return tests; 
    } 

    public List<Test> getPreTests() { 
     List<Test> preTests = new ArrayList<Test>(); 
     for (Test test : preTests) { 
      if (test.isPreTest()) { 
       preTests.add(test); 
      } 
     } 
     return preTests; 
    } 


    public List<Test> getPostTests() { 
     List<Test> postTests = new ArrayList<Test>(); 
     for (Test test : postTests) { 
      if (test.isPostTest()) { 
       postTests.add(test); 
      } 
     } 
     return postTests; 
    } 
+0

Merci, Stevi, mais je ne suis pas sûr d'avoir abandonné la méthode "Table par hiérarchie de classes" - c'est comme ça que j'ai placé l'héritage, mais j'ai quand même l'erreur "unknown target entity entity". À moins que vous ne suggériez peut-être de déplacer le champ 'cours' vers les classes enfants, ou de manipuler la hiérarchie des classes pour faire croire à Hibernate? Les deux autres suggestions sont raisonnables, mais inélégantes - IMO légèrement moins élégant que celui que j'ai suggéré. – Michael

+0

Je ne suis pas sûr d'après ce que je vois dans votre question pourquoi vous obtiendriez une "propriété d'entité inconnue", donc je ne peux pas en parler. J'ai ajouté un exemple de code pour la troisième option. Non, ce n'est pas la solution la plus élégante, mais j'ai tendance à être plutôt pragmatique dans mon approche d'Hibernate. –

Questions connexes