【问题标题】:JPA - @OneToMany updateJPA - @OneToMany 更新
【发布时间】:2012-01-16 02:49:18
【问题描述】:

假设有两个实体,Department 和 Employee,其中一个部门有 N 个员工。

在部门:

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

非常感谢!

【问题讨论】:

    标签: hibernate jpa annotations one-to-many


    【解决方案1】:

    明确的答案是:不,您的 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;
      }
    }
    

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

    【讨论】:

      【解决方案2】:

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

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

      如果您已经实现了一项服务,那么您可以提供一个服务调用来负责管理此类内容,那么您将不会有很大的机会在代码中的某个位置忘记它并且在其他 15 个地方正确执行。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-30
          • 1970-01-01
          • 1970-01-01
          • 2013-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-04-04
          相关资源
          最近更新 更多