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

use*_*556 1 java hibernate jpa self-reference

我有一个“问题”实体,可以将其保留到“问题”表中。一个问题可以有多种翻译。翻译只是另一种语言的另一个问题,与其带有parent_id字段的父问题相关联。因此,问题表具有 Question_id (int)、parent_id (int)、语言 (varchar)、prompt 等列。在我的设计中,parent_id 与翻译的 Question_id 相同。例如,假设我有一个 id 为 13 和 17 的英文问题(默认),而问题 13 有 3 个翻译:中文、日文和韩文。那么问题表将如下所示:

Question_id Parent_id 语言

13 13 英语;14 13 中文;15 13 日语;16 13 韩语;17 17 英语

在 Question 对象中,我想将问题与其翻译的关系映射为 @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....
}
Run Code Online (Sandbox Code Playgroud)

但是,由于它是自引用关系,我不理解以下内容:

  • 这是单向关系还是双向关系?
  • 注释cascade = CascadeType.PERSIT 对“parent”字段有何影响,或者在这种情况下意味着什么?
  • 是否可以将“parent”字段替换为整数“parent_id”并仍然保持关系?换句话说,我可以只用整数“parent_id”来跟踪父级,而不是像现在这样拥有整个 Question 对象: private Question Parent

Gui*_*rmo 6

  • 这是单向关系还是双向关系?

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

  • 注释cascade = CascadeType.PERSIT 对“parent”字段有何影响,或者在这种情况下意味着什么?

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

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

  • 是否可以将“parent”字段替换为整数“parent_id”并仍然保持关系?换句话说,我可以只用整数“parent_id”来跟踪父级,而不是像现在这样拥有整个 Question 对象: 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;
Run Code Online (Sandbox Code Playgroud)

一些注释,

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