我们正在使用 Spring MVC 3.2、Jackson 1.9.12、Hibernate 4.2.2 构建 REST-API。
昨天我需要将一个小对象图传递给 API,它应该保存在数据库中。它有些工作,我可以为这些问题构建解决方法,但我认为必须有一个更好的解决方案。
所以这就是我们所拥有的:
- 班级
Bill
- 班级
Contact
- 班级
Address
- 班级
Item
关系是:
Bill
与 有两个OneToOne
关系Contact
。一叫sender
,一叫receiver
。Bill
与 有ManyToOne
关系Item
,称为item
。Contact
与 有OneToOne
关系Address
,称为address
。
(这可能看起来有点愚蠢,但我省略了一些字段和其他关系,以解决问题)
第一个问题 - 简单案例 - 覆盖数据库条目:
让我们忽略所有这些依赖和关系,只使用普通Bill
类。如果有一个不包含对象 ID 的传入 JSON 请求,一切都会按预期工作,并且 Spring/Hibernate 在数据库中创建一个新条目:
{ ...
"createdAt":"2013-05-29"
}
但是如果我在 JSON 请求中指定一个 id,Spring/Hibernate 将更新包含给定 id 的行:
{ ...
"id":"c5a562d0-c8ab-1c42-8399-080012345678"
"createdAt":"2013-05-29"
}
如果我在 JSON 请求中指定了一个 ID,但该 ID 在数据库中不存在,它将创建一个新条目。
我使用的代码没什么特别的。这是控制器动作:
@RequestMapping(value = "/create", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.CREATED)
public Bill create(@RequestBody Bill bill) {
bill = service.createBill(bill);
return bill;
}
以及服务方法:
@PreAuthorize("isAuthenticated()")
@Transactional
public Bill createBill(Bill bill) {
bill = billDao.store(bill);
return bill;
}
如您所见,我想使用/create
路径来创建新条目,而不是更新现有条目。作为一种解决方法,我当然可以在setId(null)
控制器操作的第一行使用,但是有没有更好/更好的方法?
第二个问题 - 另一个 id 的东西 - 如何正确设计实体?
我们再次得到上面的对象图:
"bill":{ ...
"sender":{ ...
"address":{ ... }
},
"receiver":{ ...
"address":{ ... }
},
"item":{ ... }
}
Contact
(and Address
) 和之间存在逻辑上的区别Item
:
- A
Contact
(andAddress
) 由一堆新数据组成。意味着:GUI 将显示很多输入字段,用户必须填写这些字段。 - An
Item
已经在数据库中,我基本上只需要它id
,而不是整个对象。这意味着:GUI 将显示一个包含所有现有Item
s 的下拉列表,用户必须选择其中一个。
现在我当然想使用(和重用)我的实体,但是我的Bill
实体例如需要一个Item
对象,而不是item_id
. 作为一种解决方法,我当然可以创建另一个 bean,它与类几乎相同Bill
,但item
它包含一个item_id
:
"the_new_special_bill_for_incoming_json":{ ...
"sender":{ ...
"address":{ ... }
},
"receiver":{ ...
"address":{ ... }
},
"item_id":{ ... }
}
再说一遍,同样的问题:有更好/更好的方法吗?
感谢你们!