Spring Boot,我有一个Rest控制器,我正在尝试用父节点保存一个对象。
@Entity
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JsonManagedReference()
private List<Child> children;
// getters / setters
}
@Entity
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@JsonView(Views.Summary.class)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
@NotNull
@JsonBackReference()
private Parent parent;
// getters / setters
}
由于@JsonBackReference
,Jackson不会完全序列化Child对象,包括Parent。所以在我的测试中做类似以下的事情是行不通的......
Child child = new Child()
child.setParent(parent)
ObjectMapper mapper = new ObjectMapper()
String payload = mapper.writeValueAsString(child);
我最终得到以下JSON:
{ "id": null }
我真正想要的是
{ "id": null, parent: { "id": 1 } }
所以我决定将父ID添加为@PathVariable
,然后将其传递给我的服务方法,并手动设置。问题是,因为Parent
在Child中不能为null,并且我使用@Valid
验证了Child,所以我甚至没有进入我的方法的关键所以我可以处理父ID
@RequestMapping(value = "/{parentId}/children", method = RequestMethod.POST)
public void save(@PathVariable Long parentId, @Valid @RequestBody Child child, BindingResult bindingResult, HttpServletRequest request, HttpServletResponse response) {
if (bindingResult.hasErrors()) {
throw new InvalidRequestException("Invalid Child", bindingResult);
}
this.storeService.save(parentId, child);
response.setHeader("Location", request.getRequestURL().append("/").append(child.getId()).toString());
}
任何建议都非常受欢迎。
答案 0 :(得分:2)
您的JPA模型(正如您所写)表示Parent
对象包含Child
个对象的列表。此外,使用cascade = CascadeType.ALL
表示这是应该管理Parent
对象的Child
对象,而不是相反。
换句话说,如果您想保存数据,则需要:
Parent
对象(确定)Child
对象(确定)每次需要更新子项时,请在父项中进行修改,然后保存父项。
这就是为什么这与序列化孩子中父母的id无关。
此外,我建议您将orphanRemoval=true
添加到@OneToMany
注释中,以便不再删除与其父级不相关的子项
更新(澄清):
如果您正在使用级联(如果它是级联ALL,则更多),您不会告诉应用程序您要更新Child
实例。您所做的是更新其父级中的子级,然后保存父级。级联将完成其余的工作。