7

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?

DiveInto
  • 2,158
  • 3
  • 27
  • 50

3 Answers3

6

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

AsSiDe
  • 1,826
  • 2
  • 15
  • 24
  • 1
    Be careful, and watch to not have @JoinColumn(..., "insertable = false, updatable = false"), that would mean not to insert or update that column, and "hospital_id" would not be set. – Seba Cervantes Jun 12 '19 at 02:14
0

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

@ManyToOne
@JoinColumn(name = "hospital_id", nullable = false)
Aleksandr Podkutin
  • 2,532
  • 1
  • 20
  • 31
0

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)

SkyWalker
  • 28,384
  • 14
  • 74
  • 132