Problem: A Hibernate bi-directional One-to-Many relationship does not map easily to JSON. If default (Jackson) mapping is used there is an infinite recursion issue as the parent contains the children each of which contains a reference to the parent. The easiest way I've found to fix this is to mark the Many end attribute as @JsonIgnore. This means that the JSON gets generated as expected. However, when the objects are sent over a REST POST (for example) this means the ManyToOne references get lost. At present I just have the REST service reconstruct the references before persisting the data, but I'm wondering if there is a recommended way to do this automatically (using the Spring REST architecture).
To illustrate, here are some code snippets:
The parent Entity:
@Entity
@Table(name = "wine_case")
public class WineCase {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "wineCase")
private List<CaseContent> caseContents;
}
The child Entity:
@Entity
@Table(name = "case_content")
public class CaseContent {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "wine_case_id", nullable = false)
@JsonIgnore
private WineCase wineCase;
}
The method in the REST controller which receives the request, and needs to rebuild the relationships back from CaseContent to WineCase:
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
public @ResponseBody
WineCase createWineCase(@RequestBody WineCase wineCase, HttpServletResponse response) {
wineCase.setId(null);
wineCase.getCaseContents().forEach((cc) -> cc.setWineCase(wineCase));
entityManager.persist(wineCase);
response.setHeader("Location", "/winecases/" + wineCase.getId());
return wineCase;
}
Best Answer
Since you're using jackson you should take a look at this : https://github.com/FasterXML/jackson-datatype-hibernate
With this module, jackson will not serialize LAZY fields if you didn't initialize them, so you could have LAZY fields on both sides to not have any problems.
If this solution does not suit to your needs (maybe you want some eager). Then instead of use @JsonIgnore use @JsonIgnoreProperties like this :
The properties exclusion will make sure that you don't serialize cycles whereever you start (ie from child or from parent). The allowSetters will allow deserialisation of the properties, only serialisation will ignore the defined properties in the annotation ( the allowSetters/Getters exists since 2.6).
Be aware that there is currently a bug with jsonignoreproperties and lazy objects : https://github.com/FasterXML/jackson-datatype-hibernate/issues/78. Let's hope it'll be fixed for 2.8.