Spring @RequestBody没有查找对象

时间:2015-03-30 09:19:55

标签: hibernate spring-mvc

我正在使用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对象。我错过了什么吗?

2 个答案:

答案 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属性帐户映射到您的帐户变量