JPA / Hibernate关系单向工作

3

我有一个父表和子表之间的多对多关系。

这是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>();

这是我子类中的部分代码:

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

现在,如果我定义了一个名为child的Child对象和一个名为parent的Parent对象,从父级方面添加子级将起作用:

parent.getChildren().add(child);

这会在数据库中正确更新,并将条目保存到parents_children表中。

但是当我从另一端尝试进行操作时,也就是从子代那里,我想设置父代。如果我已经定义了Set<Parent> parents并且在我的Children类中定义了updateParents()方法,并且我从数据库中加载了一个孩子定义为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个回答

3
不,你的定义没有问题。问题在于children是关联的拥有方,除非将子对象添加到该集合中,否则数据库不会更新。
你可以改变parents来映射同一个表格,即删除mappedBy,从而有效地使用两个单向关联,但这可能会在更新父对象和子对象时引起问题。
考虑以下情况:
  • 对象A有子对象B和C
  • 对象B有父对象A
  • 对象C没有父对象(A不在parents集合中)
现在你要更新A和C。C是否仍然是A的子对象?信息是矛盾的。
为了解决这个问题,只有一侧应负责更新关系,在您的情况下是A(通过其children集合)。

0
在JPA中,您负责管理关联的双方。这意味着您必须明确设置关系的一侧上的一个字段,并在多侧上添加一个元素到集合中。
例如,考虑一个具有字段List<Course>Student实体,并假设两个实体StudentCourse之间存在双向OneToMany/ManyToOne关系。
在为Student添加Course时,您需要管理关系,例如:
Course course = //findFromSomewhere;
Student student = //findEntity;

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

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

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

仅仅因为你在一个实体上插入/更新了一个字段,并不意味着Hibernate/JPA会自动为你更新关系的另一侧。像这样持久化不会更新关联的另一侧:

   //This would fail to add the course to the students list of courses.
   course.setStudent(student);
   em.persist(course);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接