java - 如何使用 REST API 将子对象添加到父对象?
问题描述
抱歉,如果这个问题看起来很奇怪,我对 REST API 有点陌生!
我有两个实体:订单和项目。
一个订单可以有多个商品,一个商品只能有一个订单。
使用 Spring Boot,我在对应关系中设置了两个实体,并且每个实体在指定的基本路径 /api 上都有自己的端点。
我可以很好地添加订单或商品,但是,我正在尝试弄清楚如何将商品直接添加到订单中。
如果我创建了一个新的 Order 并且它具有路径api/orders/1
,则它表明其中也引用了一个项目列表api/orders/1/items
。但是,如果我尝试向该 url 发布一个新项目,它就不起作用。
我也尝试在 url 创建一个新项目api/items
,这很有效,但此时我不知道如何将项目的父项设置为订单。
我也在使用 Postman 来完成这项任务。
谢谢你的帮助。
解决方案
简短回答:使用订单 URL 作为参考发布到 /items:
curl -X POST -H "Content-Type:application/json" -d '{"name": "foobar", "order": "http://localhost:8080/orders/1"}' http://localhost:8080/items
冗长(冗长)的回答:通俗地说,“ REST ”指的是一种松散的架构风格,用于通过 HTTP 提供 Web 服务。有很多最佳/常见做法,但没有太多规则。一些存在的规则通常被忽略/破坏。从技术上讲,这些规则来自原始论文,如果您忽略它们,有些人会告诉您服务不是 RESTful,因为 REST 有一个精确的定义。
大多数人在实践中忽略的是 HATEOAS,它是客户端应该能够与服务交互并使用超媒体在没有任何先验知识的情况下发现所有端点的主体。这类似于作为人类您可以浏览到站点的主页并通过单击链接逐页导航的方式。
Spring Data REST 提供了一种将数据存储库公开为超媒体驱动服务的简单方法。对其他实体的引用作为 URL 而不是普通 ID 传递。要创建属于订单的商品,您首先需要订单的 URL。然后您可以发布到项目集合:
curl -X POST -H "Content-Type:application/json" -d '{"name": "foobar", "order": "http://localhost:8080/orders/1"}' http://localhost:8080/items
老答案:
如果不查看任何代码,很难说出了什么问题,但您需要确保端点/api/order/{id}/items
具有 PostMapping 和 GetMapping。
关于 API 设计,我建议您使用更扁平的版本,您可以通过 POST 来创建项目,/api/items
并在 body over 中使用订单 ID /api/orders/1/items
。这更符合数据库规范化,并且更清楚哪个控制器应该处理哪些请求。
订单表不应存储任何商品 ID。项目条目存储它们的订单 ID。要获取订单中的商品列表,请按订单 ID 过滤所有商品。
POST /api/items
{
"orderId": 123,
"skuId": 234,
"price": 42.10,
"gift": false
}
对比
POST /api/orders/123/items
{
"skuId": 234,
"price": 42.10,
"gift": false
}
在你的 ItemController 你可以有类似的东西
@PostMapping
public Item createItem(@RequestBody ItemRequestDTO) {
...
}
其中 ItemRequestDTO 是另一个类,其中仅包含创建项目所需的字段,包括订单 ID。
PS 我猜在某些时候你会使用数据库来持久化,在这种情况下你可以使用@ManyToOne 和@OneToMany映射。
推荐阅读
- kivy - remove_widget kivy 不按名称删除
- spring-boot - CrudRepository 上的错误。白标错误页面
- android - Flutter 中的 Image_picker 依赖项不允许我使用错误消息编译我的应用程序
- powershell - Sharepoint 时区更改 Powershell
- reactjs - React chartjs - 图表保持为空,除非图例被点击两次
- javascript - 如何使用 Javascript 验证 HTML 表单
- typescript - 是否可以根据特定泛型类型参数的存在动态设置泛型函数中函数参数的类型?
- typescript - TypeScript 单元测试不能在模块外使用 import 语句
- swift - 如何在swift 5中更新标记而不重新加载谷歌地图
- android - 应用程序进入后台后自动销毁子片段 - Android