我有一个用于数据模型的REST接口,它在实体之间具有多个一对多和多对多关系。虽然多对多关系似乎很容易无国籍地管理,但我遇到了一对多的问题。考虑以下一对多关系:
员工:
@ManyToOne
@JoinColumn(name = "Company_id")
private Company company;
公司:
@OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval=true)
public Set<Employee> employees = new HashSet<Employee>();
更新公司时,其员工集合也可能已更新(员工已删除或添加)但由于REST界面仅允许更新公司,因此我无法明确删除或添加员工。
简单地更换集合不起作用,但我发现这似乎有效:
public void setEmployees(Set<Employee> employee) {
this.employees.clear(); // magic happens here?
this.employees.addAll(employees);
for (Iterator<Employee> iterator = employees.iterator(); iterator.hasNext();) {
Employee employee = (Employee) iterator.next();
employee.setCompany(this);
}
}
这是应该做的,还是有更好的方法?
编辑:事实上以上不起作用!它似乎首先起作用,但随后它会破坏:Exception in thread "main" java.lang.IllegalStateException: An entity copy was already assigned to a different entity.
我认为这是因为数据库已经包含一组员工,如果任何“旧”员工也是替换集的一部分,他们就会与数据库中的员工发生冲突。
那么更换套装的正确方法是什么?
答案 0 :(得分:3)
首先确保正确实施等于。根据hibernate规范:http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch04.html#persistent-classes-equalshashcode
我在合并时遇到了类似的问题。基本上我必须获取与公司相关的现有员工。我必须将任何更改合并到现有员工,然后添加任何新员工。
Query query = em.createQuery("select e from Employee e where e.company = '" + company.getId() + "'");
Collection<Employee> existingEmployees = new LinkedList<Employee>();
try{
Iterables.addAll(existingEmployees, (Collection<Employee>) query.getResultList());
}
catch(NoResultException nre){
//No results
}
for(Employee existingEmployee : existingEmployees){
for(Employee employee : company.getEmployees()){
if(existingEmployee.name().equals(employee.name())){
employee.setId(existingEmployee.getId());
}
employee.setCompany(company);
}
}
答案 1 :(得分:1)
我认为你没有更好的选择来替换现有的集合,只需设置REST响应提供的新集合。