从Json正确创建的实体,在另一侧有@JoinColumn

时间:2020-10-02 08:31:39

标签: java jpa spring-data-jpa joincolumn

我以为我了解了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。

2 个答案:

答案 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;
    }
}
相关问题