我正在使用Spring-MVC / Hibernate编写REST服务,似乎@RequestBody是接受一堆参数并将其映射到POJO的推荐方法。但是,似乎通过POST发送的ID被转换为null而不是实际对象。一些示例代码将更好地解释。
服务很简单:
@ResponseBody
@RequestMapping(value="add", method = RequestMethod.POST)
public ServiceResponse addTx(@RequestBody Transaction tx) {
...
return ServiceResponse;
}
交易实体有一个账户实体:
@Entity
@Table(name="Transaction")
public class Transaction {
@Column(name="code")
private String code;
@OneToOne
@JoinColumn(name="accountId")
private Account account;
@Column(name="amount")
private int amount;
...
}
我的浏览器的POST请求有效负载为:
{code: "ascasc", amount: 23, accountId: 1, ... }
但是在服务器端,构造的Transaction对象的Account值为null。即accountId为1并未转换为Account对象。我错过了什么吗?
答案 0 :(得分:3)
您描述的行为是正确的。当您使用@RequestBody
时,它对您的持久层一无所知,只是将请求的主体映射到目标对象。
因此,当您发布包含accountId
的JSON时,Spring将尝试查找目标对象的accountId
属性,但它不存在(目标对象只有account
属性),所以accountId
将不会被映射。如果您希望正确映射accountId
,则必须像{..., account: { id: 1 }, ...}
一样POST JSON。
另一方面,将传输对象用于Web服务的请求/响应对象然后将它们映射到实体对象是一种相当常见的模式。然后,您可以在传输对象中具有accountId
属性,然后在组装实体时使用该值。其中一个原因可能是您不希望从Web服务返回某些模型属性,并且您不希望使用@JsonIgnore
注释污染模型层。这种方法还可以让您更改实体类(例如重命名某些属性),而不必破坏您的API。然而,这将增加额外的复杂性,因此您必须决定它是否值得。
答案 1 :(得分:2)
你也可以使用注释@JsonProperty - 如果你使用的是jackson
@OneToOne
@JoinColumn(name="accountId")
@JsonProperty("account")
private Account account;
这会将json属性帐户映射到您的帐户变量