我以为我了解了JPA的 @JoinColumns 批注和 mappedBy 参数,但是随后我需要根据这个 Question 问题的Json创建新实体>。它具有一组答案选择,这些答案也需要映射到新实体。我决定Question实体将成为拥有方,因此我省略了mappingBy参数。当我在 AnswerChoice 端使用@JoinColumns批注时,所有实体都是从Json对象创建的,但是没有设置AnswerChoices对Question实体的FK。
将@JoinColumns放到Question实体中解决了问题,但是我的问题是:这是正确的方法吗?我会面临任何副作用吗?相反,我应该在AnswerChoices集合上运行for循环并设置FK吗?
问题杰森
{
"text": "Do you know JPA?",
"answerChoices": [{
"text": "yes",
}, {
"text": "no",
}, ]
}
具有JpaRepository的控制器:
@PostMapping("/questions/create")
@ResponseBody
public String create(@RequestBody Question json) {
questionRepo.save(json);
}
问题实体:
@Entity
public class Question {
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
@JoinColumn(name="question_id")
private Set<AnswerChoice> answerChoices;
}
AnswerChoice实体:
@Entity
public class AnswerChoice {
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnore
private Question question;
}
为了简洁起见,我省略了自动生成的ID。
答案 0 :(得分:3)
不是,映射不正确。实际上,它创建两个碰巧共享连接列的单独关联。
从question
中删除Answer
,使关联成为单向关联(如果您确实需要关联的那一面,请问问自己),或者返回原始解决方案并使用@JsonBackReference/@JsonManagedReference
(因此在反序列化期间该字段会自动填充)。
答案 1 :(得分:3)
如@crizzis所述,您的映射是不正确的,通常,孩子是关系的所有者(当一对多对一个域很大时),但是在您的情况下,{{1 }}是关系的拥有方,因为您拥有Question
。因此,您可以完全摆脱@JoinColumn
的{{1}}参考。当您创建带有“答案”选项的“问题”时,休眠状态将
如果您从Question实体中删除此行Question
,则hibernate将创建额外的表来管理称为AnswerChoice
的这种关系,因此要摆脱多余的表,我们将手动指定{{ 1}}映射到外键。
实体@JoinColumn(name = "question_id", foreignKey = @ForeignKey(name = "fk_question_id"))
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;
}
}
生成的表语句如下:
questions.sql
AnswerChoice.java
answer_choice.sql
@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;
}
}