为什么hibernate没有在OneToMany的所有者端设置外键

时间:2016-08-01 16:41:39

标签: java hibernate jpa spring-boot jackson

我有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 Object,其中包括医院和部门。

在我拯救医院之后,我找到了外键:部门中的'hospital_id'未设置。

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

3 个答案:

答案 0 :(得分:4)

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

修改您的代码如下(包含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可用于新版本的杰克逊

答案 1 :(得分:0)

@ManyToOne注释中删除级联,并将nullable = false添加到JoinColumn

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

答案 2 :(得分:0)

您可以将获取类型用作惰性。在连接列中,使其不为空。

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