1

I am trying to save 2 objects via RESTFUl service in a form which has nested relationship. I.e., an office has 2 employees.

However, as you can see from the following sample, without saving the office first, I won't be able to know the officecode as 20. Without:

"officecode":"20"

Although the json object is nested, however, I saved employees and offices OK, but they are not associated to each other.

How can I save nested objects in 1 submit then?

Entity looks like:

    // Property accessors
    @Id
    @Column(name = "OFFICECODE", unique = true, nullable = false, length = 10)
    public String getOfficecode() {
        return this.officecode;
    }
....


    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "office")
    public Set<Employee> getEmployees() {
        return this.employees;
    }

Here is the rest call to save the office:

@RequestMapping(value = "/Office", method = RequestMethod.POST)

@ResponseBody

public Office newOffice(@RequestBody Office office) {

officeService.saveOffice(office);

return officeDAO.findOfficeByPrimaryKey(office.getOfficecode());

}

Here is the JSON object I have posted:

{
"state":"CA",
"country":"USA",
"officecode":"20",
"city":"Vancouver",
"phone":"+1 650 219 4782",
"addressline1":"100 Market Street",
"addressline2":"Suite 300",
"postalcode":"94080",
"territory":"NA",
"employees":[
{
"extension":"x5800",
"employeenumber":2001,
"lastname":"joe",
"firstname":"joe",
"email":"joe@classicmodelcars.com",
"reportsto":null,
"jobtitle":"President",
"pay":null,
"officecode":"20"
},
{
"extension":"x5800",
"employeenumber":2002,
"lastname":"mary",
"firstname":"mary",
"email":"mary@classicmodelcars.com",
"reportsto":null,
"jobtitle":"Vice President",
"pay":null
"officecode":"20"
}
]

}
atl_ala
  • 35
  • 6

1 Answers1

4

OK you are using Cascade, but it still does not work. This is because of the way employees are being added to the office.

The JSON unmarshaller is associating the employees like this:

office.getEmployees().add(employee)

This is not sufficient to link the employee to the office, because the office.getEmployees is the non-owning side of the relation, that Hibernate does not track.

The result is that office and employees are all inserted, but the foreign key from employee to office is null.

To solve this, before saving you need to link all the employees to the office, by adding this method to Office and calling it right before persist:

public void linkEmployees() {
    for (Employee employee : employees) {
        employee.setOffice(this);
    }
}

This way the owning side of the relation (Employee.office) is being set, so Hibernate will be notified of the new association and persist it by populating the foreign key field from employee to office.

See here my answer in this thread if you want to know more about Hibernate bi-directional relations and the ocasional need for a owning side.

Community
  • 1
  • 1
Angular University
  • 42,341
  • 15
  • 74
  • 81
  • Strange, my @OneToMany is at different place, I have updated the question to reflect that. Thx. – atl_ala Jan 11 '14 at 20:59
  • I update the answer on this thread concerning the owning side and why this behavior of saving employee with a null foreign key is normal and what to do about it http://stackoverflow.com/questions/2749689/what-is-the-owning-side-in-an-orm-mapping/21068644#21068644 – Angular University Jan 11 '14 at 22:31