2

我有一个用于数据模型的 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.

我假设发生这种情况是因为数据库已经包含一组员工,并且如果任何“旧”员工也是替换集的一部分,它们会与数据库中的员工发生冲突。

那么更换套装的正确方法是什么?

4

2 回答 2

3

首先确保正确实施equals。根据休眠规范: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);
        }
    }
于 2013-03-26T16:22:52.610 回答
1

我认为您没有更好的选择来替换现有集合并简单地设置 REST 响应提供的新集合。

于 2013-03-25T11:14:04.917 回答