JPA - @OneToMany更新

时间:2011-12-08 17:13:04

标签: hibernate jpa annotations one-to-many

考虑到有两个实体,即部门和员工,其中一个部门有N名员工。

在Departament:

@OneToMany(mappedBy = "department", fetch = FetchType.EAGER)
private Collection<Employee> employees = new ArrayList<Employee>();

在员工中:

@ManyToOne(fetch = FetchType.EAGER)
private Department department;

一切正常,但我想在不设置反向关系的情况下将员工添加到部门。例如:

// I will add two employees to a department
department.getEmployees().add(employee1);
department.getEmployees().add(employee2);

// In fact, it is necessary to set the opposite side of the relationship
employee1.setDepartment(department);
employee2.setDepartment(department);

entityManager.merge(department);      
//...

所以,我的问题是:是否有某种方式(例如通过一些注释)JPA会理解它应该将更改传播到关系的另一端而不是我明确的那样?换句话说,我只想这样做:

department.getEmployees().add(employee1);
department.getEmployees().add(employee2);
entityManager.merge(department);

非常感谢!

3 个答案:

答案 0 :(得分:3)

明确的答案是:不,您的JPA提供商不可能像您描述的那样自动处理双向关系。

然而,您可以实现在您的实体中设置双向关联的逻辑,可能是这样的:

class Department {

  public void addEmployee(Employee empl) {
    if (empl.getDepartment() != null && !this.equals(empl.getDepartment())) {
      empl.getDepartment().getEmployees().remove(empl);
    }
    empl.setDepartment(this); // use the plain setter without logic
    this.employees.add(empl);
  }
}


class Employee {
  // additional setter method with logic
  public void doSetDepartment(Department dept) {
    if (this.department != null && !this.department.equals(dept)) {
      this.department.getEmployees().remove(this);
    }
    dept.getEmployees().add(this);
    this.department = dept;
  }
}

在这种情况下,您必须确保在持久性上下文之外处理实体时已初始化关联,以避免延迟初始化异常。这可能会迫使您切换到所有关联的预先加载,这通常不是一个好的选择。 由于双向关联的复杂性,我个人避免实体中的双向关联,只有在有充分理由的情况下才使用它们。

答案 1 :(得分:2)

JPA不会为您管理您的Java对象图。您可以像在问题中那样自己更新对象图,或者我猜您可能在保存后重新加载所有实体。

我不喜欢双向关系,因为它们会变得混乱,但如果你必须这样做,那么你可能会想要选择一方作为关系的“拥有”方。在此页http://www.objectdb.com/java/jpa/entity/fields上查找有关“mappedBy”的内容,以获取有关如何执行此操作的信息。

如果你有一个已实施的服务,那么你可以提供一个服务电话,负责管理这类东西,那么你就没有机会在你的代码中的一个地方忘记它在其他15个地方正确地做到了。

答案 2 :(得分:1)

唯一的方法就是明确,就像你提到的那样。