简体   繁体   中英

why hibernate not set foreign key in the owner side of OneToMany

I have 2 Entities, Hospital and Department, Department reference its hospital by hospital_id in it.

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

I use Rest API to create instance of Entities:

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

    return hospital;
}

I post json payload to create a Hospital:

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

Since I use SpringBoot, Jackson will auto parse the json payload into Java Object, here its Hospital and Departments in it.

While after I save the hospital, I found the foreign key: 'hospital_id' in department is not set.

Why is this and if possible, how can I make the foreign key set when I save the hospital object?

You should always create an association in owner side before persisting an entity because owner side is responsible for creating relationships.

Modify your code as below (Contains Java 8 Code):

@RequestMapping("/create")
@ResponseBody Hospital create(@RequestBody Hospital hospital){

    hospital.getDepartments().forEach(department->department.setHospital(hospital));
    hospital = hospitalService.save(hospital);

    return hospital;
}

You may face a new problem when converting entity to json because Jackson serializes related entities recursively and you'll get StackOverflow Error. To resolve this issue add @JsonManagedReference along with @OneToMany annotation and @JsonBackReference along with @ManyToOne annotation.

Note: @JsonManagedReference and @JsonBackReference available in new version of Jackson

Remove cascade from @ManyToOne annotation and add nullable = false to JoinColumn

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

You can use fetch type as lazy. In joining column, make it not null.

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

Resource link:

Hibernate – One-to-Many example (Annotation)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM