2012-08-13 2 views
0

Je voulais implémenter une relation un-à-un en utilisant Hibernate et JPA. J'ai deux classes qui font partie d'une hiérarchie: Hiérarchie de question et hiérarchie de réponse.Hibernate, JPA - unidirectionnel un-à-un

@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public abstract class QuestionUnit { 

    @Id 
    @GeneratedValue(strategy = GenerationType.TABLE) 
    private int id; 

    @OneToOne(cascade = CascadeType.ALL)  
    @PrimaryKeyJoinColumn 
    private AnswerUnit correctAnswer; 
...} 


@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public abstract class AnswerUnit { 

    @Id 
    private int id; 

    public abstract Object getAnswerContent(); 

    public abstract boolean isEqual(AnswerUnit otherAnswer); 

    public int getId() { 
     return id; 
    } 
} 

et nous avons OpenQuestion et OpenAnswer en tant qu'implémentations.

Je voulais que la table avec OpenQuetions ait une clé primaire générée automatiquement, et que la table avec OpenAnswer ait une clé primaire ayant la même valeur que la clé primaire dans la table OpenQuestion. J'ai essayé de suivre l'exemple d'ici: http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html partie 2.2.5.1. Un par un.

Mais quand je persiste le OpenQuestion, je reçois la table OpenQuestion avec des colonnes id, questionContent et OpenQuestionAnswer avec id, answerContent, mais les valeurs des ids ne correspondent pas.

Alors, où est-ce que je fais une erreur?

Répondre

0

Vous n'avez pas de colonne "CorrectAnswer" dans "OpenQuestion"?
Cela devrait être la clé étrangère à la colonne ID à "OpenAnswer" -
i.e - ceux-ci devraient être les valeurs ID correspondantes.
Si vous n'avez pas cette colonne - je suppose que vous avez une sorte d'erreur dans votre mappage JPA.
Édition - pour moi-même -
Veuillez ajouter MappedSuperClass. Lisez here à ce sujet.

+0

qui est le point, comme je l'ai dit, en OpenQuestion je n'ai que '' id' et questionContent', et tout le mapping est e Je pense que le code. – Andna

+0

Vous avez également besoin de @MappedSupperClass - s'il vous plaît voir ma réponse éditée. Il m'a fallu du temps pour m'en souvenir. –

+0

Je ne peux pas utiliser MappedSuperClass, vous ne pouvez pas utiliser les mappages dans des classes qui ne sont pas annotées avec entity, et j'ai une classe QuestionList qui a ArrayList de QuestionUnits. – Andna

0

Je ne suis pas sûr de ce que vous essayez de faire, Pourquoi avez-vous une relation un à un de question à répondre ?? La logique me dit qu'une question peut avoir beaucoup de réponses (et probablement une seule bonne réponse).

Et en utilisant cette approche, vous ne devriez pas besoin de se soucier d'être l'égale des deux id, si c'est le cas, vous devriez avoir un modèle comme celui-ci:

@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public abstract class QuestionUnit { 
    @Id ... private int id; 
    @OneToMany private List<AnswerUnit> answers; //optional assuming there's a list of answers for every question 
    @ManyToOne private AnswerUnit correctAnswer; 

    public void setCorrectAnswer(AnswerUnit answer){ 
     if(answer.getQuestion().equals(this)){ //or maybe instead answer.setQuestion(this) 
      this.correctAnswer = answer; 
     }else{ 
      throw new RuntimeError("Answer does not belong to this question"); 
     } 
    } 

    //Other getter and setters 
    //Override the "equals" method!!! 
} 


@Entity 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
public abstract class AnswerUnit { 
    @Id private int id; 
    @OneToMany private QuestionUnit question; 

    public abstract Object getAnswerContent();  
    public abstract boolean isEqual(AnswerUnit otherAnswer); //should't you just overwrite the equals method in here?  
    //Other getter, setters, etc 
} 

Et puis l'utiliser, quelque chose comme ça :

QuestionUnit q = new OpenQuestion(); 
List<AnswerUnit> answers = new List<OpenAnswer>(); 

AnswerUnit a1 = new OpenAnswer(); 
AnswerUnit a2 = new OpenAnswer(); 
AnswerUnit a3 = new OpenAnswer(); 

a1.setQuestion(q); 
a2.setQuestion(q); 
a3.setQuestion(q); 

//Also set the contents and other required info for the questions... 

//And then associate the instances: 
q.setAnswers(answers); 
q.setCorrectAnswer(a3); 

em.persist(q); 

cela fonctionnerait même avec des réponses ouvertes et régulières

+0

La question n'a qu'une seule réponse car dans les classes qui implémentent cette classe abstraite, il existe un champ appelé contenu de question. Le type de ce champ dépend du type de la question. Mais toutes les questions partagent une chose - elles ont une réponse correcte, et cette réponse est aussi une sous-classe concrète de la classe concrète AnswerUnit. C'est pourquoi il y a un à un avec une réponse correcte. – Andna

+0

Mais alors, cela voudrait dire que chaque question ne peut avoir qu'une seule réponse, et dans ce cas, je vous conseille de réviser votre modèle. Peut-être faire de la réponse une entité Embedabble ou même supprimer cette entité et inclure les champs de réponse directement dans votre classe Question. –