JPA / Hibernate关系在一个方向上工作

时间:2013-10-02 08:58:04

标签: java hibernate jpa

我的父母和孩子之间有很多很多关系。

这是来自Parent类的映射此关系的部分:

@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "parents_children", 
            joinColumns = { @JoinColumn(name = "PARENT_ID", nullable = false, updatable = false) }, 
            inverseJoinColumns = { @JoinColumn(name = "CHILD_ID", nullable = false, updatable = false) })
protected Set<Child> children = new HashSet<Child>();

以下是我的Child课程中的部分:

@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER, mappedBy = "children")
protected Set<Parent> parents;

现在,当我尝试添加子项时,如果我将一个Child对象定义为child,并将一个Parent对象定义为parent,则此功能从父端起作用:

parent.getChildren().add(child);

这在db中正确更新,它将条目保存到parents_children表。

然而,当我尝试从另一端尝试时,我想要setParent(s)的孩子。如果我已定义Set<Parent> parents并且我在updateParents()类中定义了Children方法,并且我从db定义为child加载了一个子项,我尝试了这个:

public void updateParents() {
    Set<Parent> parents = //get this from somewhere

    child.setParents(parents);
    update();
}

这不起作用,我试图找出原因。如果我将我的方法修改为:

,它将起作用
public void updateParents() {
  Set<Parent> parents = //get this from somewhere

  for (Parent parent : parents) {
    parent.getChild().add(this);
  }
}

我在关系定义方面做错了吗?我暂时没有使用Java,而且我在记住这个问题上遇到了麻烦。

有人可以向我指出我做错了什么,所以我可以将父母添加到儿童对象中吗?

2 个答案:

答案 0 :(得分:3)

不,你的定义没有错。 问题是children是关联的拥有方,除非您将子项添加到该组,否则数据库将不会更新。

您可以更改parents以映射同一个表,即删除mappedBy,从而有效地使用两个单向关联,但这可能会在更新父级和子级时导致问题。

考虑这种情况:

  • 对象A有子B和C
  • 对象B有父A
  • 对象C没有父级(A不在parents集中)

您现在更新A和C. C还应该是A的孩子吗?信息是矛盾的。

要解决此问题,只有一方应负责更新关系,在您的情况下,关系将是A(通过其children设置)。

答案 1 :(得分:0)

在JPA中,您负责管理协会的双方。这意味着您必须在关系的一侧显式设置一个字段,并将元素添加到多方的集合中。

例如,考虑一个Student实体,其字段为List<Course>,并假设两个实体OneToMany和{之间存在双向ManyToOne / Student关系{1}}。

Course添加Course时,您可以管理以下关系:

Student

当从关系的反面持久化时,您将以相同的方式管理实体。

Course course = //findFromSomewhere;
Student student = //findEntity;

course.setStudent(student);
student.getCourses().add(course);

仅仅因为您在一个实体上插入/更新字段并不意味着Hibernate / JPA会自动为您更新关系的另一面。坚持这样不会更新协会的另一方:

   course.setStudent(student);
   student.getCourses().add(course);