考虑到有两个实体,即部门和员工,其中一个部门有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);
非常感谢!
答案 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)
唯一的方法就是明确,就像你提到的那样。