正如@crizzis 所说,您的映射不正确,通常,孩子处于关系的拥有方(当一对多与单个域很大时),但在您的情况下,Question
是拥有方既然你有关系@JoinColumn
。所以你可以完全摆脱Question
来自AnswerChoice
. 当您使用答案选项创建问题时,休眠将
如果你@JoinColumn(name = "question_id", foreignKey = @ForeignKey(name = "fk_question_id"))
从 Question 实体中删除这一行,hibernate 将创建额外的表来管理这种关系,question_answer_choices
因此为了摆脱额外的表,我们手动指定将引用哪个列AnswerChoice
以映射到外键。
实体Question.java
@Entity
@Table(name = "question")
public class Question {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID id;
private String description;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "question_id", foreignKey = @ForeignKey(name = "fk_question_id"))
private Set<AnswerChoice> answerChoices = new HashSet<>();
public UUID getId() {
return id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public void addAnswerChoice(AnswerChoice answerChoice) {
if (answerChoice != null) {
this.answerChoices.add(answerChoice);
}
}
public Set<AnswerChoice> getAnswerChoices() {
return answerChoices;
}
}
实体AnswerChoice.java
@Entity
@Table(name = "answer_choice")
public class AnswerChoice {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID id;
private String content;
public AnswerChoice() {
}
public AnswerChoice(String content) {
this.content = content;
}
public UUID getId() {
return id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
下面的测试代码
@Test
public void testQuestionAndAnswersTest() {
Question question = new Question();
question.setDescription("How is the weather today?");
question.addAnswerChoice(new AnswerChoice("Sunny"));
question.addAnswerChoice(new AnswerChoice("Cloudy"));
question.addAnswerChoice(new AnswerChoice("Rainy"));
question.addAnswerChoice(new AnswerChoice("Windy"));
question.addAnswerChoice(new AnswerChoice("Snowy"));
//child entities persisted together
entityManager.persist(question);
Question searchedQuestion = entityManager.find(Question.class, question.getId());
Assertions.assertNotNull(searchedQuestion);
Assertions.assertNotNull(searchedQuestion.getId());
Assertions.assertNotNull(searchedQuestion.getAnswerChoices());
Assertions.assertEquals(5, searchedQuestion.getAnswerChoices().size());
Set<AnswerChoice> answerChoices = searchedQuestion.getAnswerChoices();
for (AnswerChoice answerChoice : answerChoices) {
Assertions.assertNotNull(answerChoice.getId());
}
}
生成的表语句如下:
问题.sql
CREATE TABLE `question` (
`id` varchar(255) NOT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
answer_choice.sql
CREATE TABLE `answer_choice` (
`id` varchar(255) NOT NULL,
`content` varchar(255) DEFAULT NULL,
`question_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_question_id` (`question_id`),
CONSTRAINT `fk_question_id` FOREIGN KEY (`question_id`) REFERENCES `question` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci