杰克逊似乎没有坚持由 Hibernate 管理的双向关系
Jackson seemingly not persisting bidirectional relationship managed by Hibernate
当我 POST 对我的 REST JSON 对象 API(使用 Spring 和 Hibernate)。
映射的 superclass 与 id 字段:
@MappedSuperClass
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 11538918560302121L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
....
}
拥有 class(扩展 NamedEntity 进而扩展 BaseEntity):
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQuery(name = "Chain.byId", query = "from Chain where id=:id")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope=Chain.class)
public class Chain extends NamedEntity {
private static final long serialVersionUID = 4727994683438452454L;
@OneToMany(mappedBy = "chain", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Campaign> campaigns = new ArrayList<Campaign>();
....
}
拥有class:
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQuery(name = "Campaign.byId", query = "from Campaign where id=:id")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope=Campaign.class)
public class Campaign extends NamedEntity {
@ManyToOne
@JoinColumn(name = "chain_id")
private Chain chain;
....
}
我的RestController的相关部分:
@RequestMapping(value = "new", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public Chain saveChain(@RequestBody Chain chain) {
chainDAO.saveChain(chain);
return chain;
}
JSON请求正文:
{
"name": "mcdonald's",
"campaigns": [
{
"name": "summer1"
}
]
}
JSON 响应正文的相关部分:
{
"id": 1,
"name": "mcdonald's",
"campaigns": [
{
"id": 1,
"name": "summer1",
"rewards": [],
"startDate": null,
"endDate": null,
"chain": null,
"surveys": [],
"achievements": []
}
],
"rewards": []
}
我怀疑这实际上是使用 @JsonIdentityInfo 注释打破无限递归时的预期行为?但是,当我随后尝试请求我刚刚使用其 id 字段创建的 Chain 时,我没有看到嵌套对象(活动) 了。
我用来检索刚创建的 Chain 对象的 GET 方法:
@RequestMapping(value = "{id}", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public Chain getChain(Model model, @PathVariable int id) {
Chain chain = chainDAO.getChainById(id).get(0);
return chain;
}
JSON GET 方法的响应正文:
{
"id": 1,
"name": "mcdonald's",
"campaigns": [],
"rewards": [],
"managers": [],
"locations": []
}
如您所见,此 Chain 对象中的 campaigns 数组现在为空。
原来我没有正确处理双向关系。必须在两端明确设置关系。
@RequestMapping(value = "{id}/campaigns/new", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public Campaign saveCampaignToChain(@RequestBody Campaign campaign, @PathVariable int id) {
Chain chain = chainDAO.getChainById(id).get(0);
chain.getCampaigns().add(campaign);
campaign.setChain(chain);
chainDAO.saveChain(chain);
campaignDAO.saveCampaign(campaign);
return campaign;
}
当我 POST 对我的 REST JSON 对象 API(使用 Spring 和 Hibernate)。
映射的 superclass 与 id 字段:
@MappedSuperClass
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 11538918560302121L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
....
}
拥有 class(扩展 NamedEntity 进而扩展 BaseEntity):
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQuery(name = "Chain.byId", query = "from Chain where id=:id")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope=Chain.class)
public class Chain extends NamedEntity {
private static final long serialVersionUID = 4727994683438452454L;
@OneToMany(mappedBy = "chain", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Campaign> campaigns = new ArrayList<Campaign>();
....
}
拥有class:
@Entity
@DynamicUpdate
@SelectBeforeUpdate
@NamedQuery(name = "Campaign.byId", query = "from Campaign where id=:id")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope=Campaign.class)
public class Campaign extends NamedEntity {
@ManyToOne
@JoinColumn(name = "chain_id")
private Chain chain;
....
}
我的RestController的相关部分:
@RequestMapping(value = "new", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public Chain saveChain(@RequestBody Chain chain) {
chainDAO.saveChain(chain);
return chain;
}
JSON请求正文:
{
"name": "mcdonald's",
"campaigns": [
{
"name": "summer1"
}
]
}
JSON 响应正文的相关部分:
{
"id": 1,
"name": "mcdonald's",
"campaigns": [
{
"id": 1,
"name": "summer1",
"rewards": [],
"startDate": null,
"endDate": null,
"chain": null,
"surveys": [],
"achievements": []
}
],
"rewards": []
}
我怀疑这实际上是使用 @JsonIdentityInfo 注释打破无限递归时的预期行为?但是,当我随后尝试请求我刚刚使用其 id 字段创建的 Chain 时,我没有看到嵌套对象(活动) 了。
我用来检索刚创建的 Chain 对象的 GET 方法:
@RequestMapping(value = "{id}", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public Chain getChain(Model model, @PathVariable int id) {
Chain chain = chainDAO.getChainById(id).get(0);
return chain;
}
JSON GET 方法的响应正文:
{
"id": 1,
"name": "mcdonald's",
"campaigns": [],
"rewards": [],
"managers": [],
"locations": []
}
如您所见,此 Chain 对象中的 campaigns 数组现在为空。
原来我没有正确处理双向关系。必须在两端明确设置关系。
@RequestMapping(value = "{id}/campaigns/new", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public Campaign saveCampaignToChain(@RequestBody Campaign campaign, @PathVariable int id) {
Chain chain = chainDAO.getChainById(id).get(0);
chain.getCampaigns().add(campaign);
campaign.setChain(chain);
chainDAO.saveChain(chain);
campaignDAO.saveCampaign(campaign);
return campaign;
}