【问题标题】:why hibernate not set foreign key in the owner side of OneToMany为什么休眠不在 OneToMany 的所有者端设置外键
【发布时间】:2016-12-06 20:04:45
【问题描述】:

我有 2 个实体,医院和部门,部门通过其中的 hospital_id 引用其医院。

@Entity
public class Hospital {
    ...
    private Set<Department> departments;

    @OneToMany(mappedBy = "hospital", cascade = CascadeType.ALL)
    public Set<Department> getDepartments() {
        return departments;
    }
}

@Entity
public class Department {
    ...
    private Hospital hospital;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "hospital_id")
    public Hospital getHospital() {
        return hospital;
    }
}

我使用 Rest API 创建实体实例:

@RequestMapping("/create")
@ResponseBody Hospital create(@RequestBody Hospital hospital){
    hospital = hospitalService.save(hospital);

    return hospital;
}

我发布 json 有效负载以创建医院:

{"name":"t-hospital", "departments":[{"name": "department1"}]}

由于我使用 SpringBoot,Jackson 会自动将 json 负载解析为 Java 对象,这里是它的医院和部门。

保存医院后,发现外键:'hospital_id' in department没有设置。

为什么会这样?如果可能,我如何在保存医院对象时设置外键?

【问题讨论】:

    标签: java hibernate jpa spring-boot jackson


    【解决方案1】:

    @ManyToOne注解中移除级联并将nullable = false添加到JoinColumn

    @ManyToOne
    @JoinColumn(name = "hospital_id", nullable = false)
    

    【讨论】:

      【解决方案2】:

      您可以使用 fetch 类型作为惰性。在加入列中,使其不为空。

      @Entity
      public class Hospital {
          ...
          private Set<Department> departments;
      
          @OneToMany(fetch = FetchType.LAZY, mappedBy = "hospital")
          public Set<Department> getDepartments() {
              return departments;
          }
      }
      
      @Entity
      public class Department {
          ...
          private Hospital hospital;
      
          @ManyToOne(fetch = FetchType.LAZY)
          @JoinColumn(name = "hospital_id", nullable = false)
          public Hospital getHospital() {
              return hospital;
          }
      }
      

      资源链接:

      Hibernate – One-to-Many example (Annotation)

      【讨论】:

        【解决方案3】:

        在持久化实体之前,您应该始终在所有者方创建关联,因为所有者方负责创建关系。

        修改您的代码如下(包含 Java 8 代码):

        @RequestMapping("/create")
        @ResponseBody Hospital create(@RequestBody Hospital hospital){
        
            hospital.getDepartments().forEach(department->department.setHospital(hospital));
            hospital = hospitalService.save(hospital);
        
            return hospital;
        }
        

        在将实体转换为 json 时,您可能会遇到一个新问题,因为 Jackson 递归地序列化相关实体,您将收到 StackOverflow 错误。要解决此问题,请添加 @JsonManagedReference 以及 @OneToMany 注释和 @JsonBackReference 以及 @ManyToOne 注释。

        注意:@JsonManagedReference@JsonBackReference 在 Jackson 的新版本中可用

        【讨论】:

        • 小心,注意不要有@JoinColumn(..., "insertable = false, updatable = false"),这意味着不插入或更新该列,而“hospital_id”会没有设置。
        猜你喜欢
        • 1970-01-01
        • 2021-06-15
        • 1970-01-01
        • 1970-01-01
        • 2012-01-04
        • 2013-03-06
        • 2013-02-09
        • 2012-02-05
        • 1970-01-01
        相关资源
        最近更新 更多