2011-12-08 119 views
5

考虑有两个实体,Department和Employee,其中一个部门中有N个员工。JPA - @OneToMany更新

在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); 

非常感谢!

回答

2

明确的答案是:不,您的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对象图。你可以像你在问题中一样更新对象图,或者我猜你可能在保存后重新加载所有实体。

我不喜欢双向关系,因为他们可能会变得混乱,但如果你必须这样做,那么你可能会想要选择一方作为关系的“拥有”一方。找到它在这个页面上谈论“mappedBy”的地方http://www.objectdb.com/java/jpa/entity/fields,了解如何做到这一点。

如果你有一个你已经实现的服务,那么你可以提供一个服务调用来管理这种类型的东西,那么你就不会有在你的代码中忘记它的机会并在其他15个地方正确做到这一点。