[英]Hibernate problems with multiple associations between two classes
我在Playframework 1.2.4中使用了Hibernate。
我有兩節課:考試和問題。 問題始終具有引用考試的屬性。 考試總是有一個屬性指向一個名為specialQuestion的問題,一個屬性指向一個問題集合。
我的目標是創建一個涉及每個問題的特殊考試。 在創建考試時,我會創建一個特殊問題。 該問題已經很好地創建並保留在數據庫中, 檢查也保留了,但是在沒有引用特殊問題的情況下,匹配列用空值填充。
我不確定注解。 問題是什么 ?
此靜態方法返回默認的特殊問題
public static Question specialQuestion(Examination examination) {
Question question = new Question();
question.examination = examination;
/* Other attributes affectations */
return question;
}
在這里,它創建了考試,影響了specialQuestion屬性並持久化了對象:
Examination examination = new Examination();
examination.specialQuestion = Question.specialQuestion(examination);
examination.save();
班級考試包含以下屬性:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "examination", fetch = FetchType.LAZY)
public Set<Question> questions = new HashSet<Question>();
@OneToOne(cascade= CascadeType.ALL, mappedBy = "examination")
public Question specialQuestion;
課程問題包含:
@ManyToOne
@OneToOne
public Examination examination;
編輯:
如果如果刪除mappedBy
在specialQuestion @OneToOne
注釋和@OneToOne
在問類考試的注釋,我得到的錯誤:我無法加載實體考試了。
這是DDL的重要部分:
CREATE TABLE `question` (
`questionId` bigint(20) NOT NULL AUTO_INCREMENT,
`examination_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`questionId`),
KEY `FKBE5CA006E00B1456` (`examination_id`)
) ENGINE=MyISAM AUTO_INCREMENT=204 DEFAULT CHARSET=latin1;
CREATE TABLE `examination` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`specialQuestion` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;
您不能將@ManyToOne
和@OneToOne
添加到同一屬性,因為Hibernate需要知道哪一個是正確的。
而且,由於擁有方是“ Question
”,Hibernate應該如何知道哪個問題是特殊問題? 從數據庫的角度考慮:將關系存儲在問題表中,您最終將獲得引用同一考試的多個問題。 如果這些是無序的(一組), 您將如何根據可用數據確定特殊問題? 由於您無法做到這一點,Hibernate也不會做到這一點。
為了解決這個問題,您需要使Examination
成為specialQuestion
一面,並且可能也只有一個單向關系,即,您不將其映射到Question
(刪除mappedBy
並添加一列作為對檢查表的引用)。
您可以通過創建一個額外的實體來實現此目的,該實體實際上將充當考試和問題之間的“連接”實體。 這將使您可以靈活地將同一問題分配給多個考試,並為每個考試獨立設置特殊問題。
因此,對於包含相同問題但具有不同特殊問題的兩次考試,表格如下所示:
╔════════════════════════════════╗
║ exam_id question_id is_special ║
╠════════════════════════════════╣
║ 1 1 0 ║
║ 1 2 0 ║
║ 1 3 1 ║
║ 1 4 0 ║
║ 1 5 0 ║
║ 2 1 1 ║
║ 2 2 0 ║
║ 2 3 0 ║
║ 2 4 0 ║
║ 2 5 0 ║
╚════════════════════════════════╝
這三個實體的基本映射如下:
@Entity
public class Examination{
@Id
private int id;
@OneToMany(mappedBy = "examination")
private Set<ExaminationQuestion> examQuestions;
public Set<Question> getNormalQuestions(){
Set<Question> questions = new HashSet<>();
for(ExaminationQuestion eq: examQuestions){
if(! eq.getQuestion.isSpecialQuestion()){
questions.add(eq.getQuestion());
}
}
return questions;
}
public Question getSpecialQuestion(){
Question specialQuestion = null;
for(ExaminationQuestion eq: examQuestions){
if(eq.getQuestion.isSpecialQuestion()){
specialQuestion = eq.getQuestion();
break;
}
}
return specialQuestion;
}
}
@Entity
public class ExaminationQuestion{
@Id
private int id;
@ManyToOne
private Examination examination;
@ManyToOne
private Questions question;
private boolean specialQuestion;
}
@Entity
public class Question{
@Id
private int id;
@OneToMany(mappedBy = "question")
private Set<ExaminationQuestion> examQuestions;
}
我根據托馬斯的答案找到了一個解決方案:
在不修改架構的情況下,這些類會變成
課堂問題:
@OneToOne
@JoinColumn(name = "examination_id")
public Examination examination;
班級考試:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "examination", fetch = FetchType.LAZY)
public Set<Question> questions = new HashSet<Question>();
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "specialQuestion")
public Question specialQuestion;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.