如何实现单向一对多自引用关系?

How do I implement a unidirectional one to many self referencing relationship?

我有一个 "Question" 实体,我可以坚持 "Question" table。一个问题可以有多个翻译。翻译只是另一种语言的另一个问题,它与带有 parent_id 字段的父问题相关联。因此,问题 table 具有列 question_id (int)、parent_id (int)、语言 (varchar)、提示等。在我的设计中,parent_id 是相同的作为翻译的 question_id。例如,假设我有一个英文(默认)ID 为 13 和 17 的问题,问题 13 有 3 种翻译,中文、日文和韩文。那么问题 table 将如下所示:

question_id parent_id 语言

13 13 英语; 14 13 中国人; 15 13 日本人; 16 13 韩语; 17 17 英语

在问题对象中,我想映射一个问题与其翻译的关系,这是一个@OneToMany 自引用关系。经过一些研究后,我通过以下方式实现了它:

@Entity
@Table(name = "question")
public class Question {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;

    @ManyToOne(cascade=CascadeType.PERSIST)
    @JoinColumn(name="parent_id")
    private Question parent;

    @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
    private Set<Question> translations;

    Other properties...
    Getters and setters....
}

但是,由于是自引用关系,我不明白以下内容:

这里需要把问题和翻译分开,创建一个Question实体:

@Entity
public class Question {
  private int id;
  //other independent translation properties
}

@Entity
public class QuestionTranslation{
  private int id;

  @ManyTone
  private Question question;
  private Language language;
  private String translation'
  //more translation based info
}

这样,您就不需要父子之间的复杂关系。

  • Is this a unidirectional or bidirectional relationship?

你拥有的是自我参照的双向关系。它只是标准双向关系的一个特例。

  • What would the effect be of the annotation cascade = CascadeType.PERSIT on "parent" field or what does it mean in this case?

在这种情况下,按照您的示例,这意味着如果您在问题 14 中设置 parent 13,只需为问题 14 调用坚持,问题 13 也将被保留。

我鼓励查看 JPA 规范以了解会发生什么(这里是 JPA 2.1 spect)。

  • Is it possible to replace the "parent" field with Integer "parent_id" and still maintain the relationship? In other words, can I just keep track of the parent with Integer "parent_id" instead of having the entire Question object like I have now: private Question parent

是的,您可以进行以下替换,

//@ManyToOne(cascade=CascadeType.PERSIST)
//@JoinColumn(name="parent_id")
//private Question parent;
@Column(name="parent_id", insertable=false, updatable=false)
private Integer parentId;

//@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
@JoinColumn(name="parent_id")
private Set<Question> translations;

一些注意事项,

  • translations 集合的级联持久化选项不是必需的。由于关系不再是双向的,您可以将问题 14、15 和 16 添加到问题 13 的集合中,并将其与其集合一起保存。
  • 在常见情况下,parentId 属性将在添加问题或将其移动到某个集合时更新(这会启动更新语句来设置字段 parent_id 的值)。不需要手动修改属性,因此我添加 insertableupdateble 选项并将其设置为 false.