通过REST API处理ManyToOne实体集合的更新

ros*_*hal 8 java rest spring hibernate

我正在努力思考通过REST API处理将集合更新到另一个资源的最佳方法,并且正在寻找其他人如何看待这个过程的指导.

假设您与实体"父"(一)和"子"(许多)具有多对一关系.我的思维过程是您可以通过单个PUT端点处理更新父项的子集合.这样,更新父项子实体的端点以及将新子实体添加到父项集合的端点通过单个端点进行.请求主体将包含子实体的数组,并且端点本身将包含足够的信息以知道正在更新哪个父实体:

即PUT .../parent/{uid}/child

端点将告诉我们具有{uid}的uid的父实体是被请求的父实体并且更新它的子实体.

这种机制感觉有点奇怪.也就是说,我必须以一种方式坚持新实体,并在另一种方式中更新它们.我的更新/保存操作最好是批量执行,但批量保存和更新都很奇怪.我必须这两个,因为你无法更新新实体

有没有更好的方法来实现这一目标?关系是分层的,这意味着没有父关系,子资源就不存在了.我还希望能够批量发布POST/PUT.

我可以暴露POST与PUT的区别(使用与上面相同的端点).我有一个约束,使得子实体具有唯一的名称,因此POST必须失败以使用现有名称POST新的子实体,并且当请求主体包含名称的子实体时,PUT将不得不失败不存在.这就是我选择使用单个端点进行共享操作的原因.

Dan*_*edo 7

处理ManyToOne

关于正确处理ManyToOne关系,让我解释一下我是如何做到的,如果我要尽可能地坚持ReST原则.

嵌套资源

有几种表达关系的方法,一种是您使用路径层次结构建议的关系.您需要以下端点:

  • /parents/
  • /parents/:id
  • /parents/:id/children
  • /parents/:id/children/:id

这种选择更好地表达了儿童不能独立存在的构成关系.

一级资源

另一个选择是,如果您要应用超媒体约束(您应该将其称为API ReSTful),请执行以下操作:

  • /parents
  • /parents/:id
  • /childrens
  • /childrens/id

在创建子资源时,您将在请求正文中包含指向具有相应rel类型的父资源的链接.例如,如果使用HAL:

{
  ...
  ...,
  "_links": {
    "parent": { "href": "https://api.domain.com/parents/9283jdp92cn"}
  }
}
Run Code Online (Sandbox Code Playgroud)

这种选择更好地表达了弱关系或聚合,其中关系的两端可以彼此不存在.

安全背景

还有第三种选择,我们应该将其视为一种特殊情况.如果父资源是经过身份验证的主体,则可以隐式地将它们相互关联.例如,如果父User实体是域实体是Photos 集合的所有者,那么您可能会想要暴露以下端点:

  • /users
  • /users/:id
  • /users/:id/photos
  • /users/:id/photos/:id

鉴于只有一个User只能访问自己的Photos,这就足够了:

  • /photos
  • /photos/:id

因为经过身份验证User的端点可以通过安全上下文使用,并且可以隐式地创建关系,而无需通过分层路径或其他方式明确表达它.

其他考虑因素

根据你的问题,我发现了一些可能导致实施不良做法的信号.所以这里有一些与你的帖子有关的原则,你应该尽可能坚持(务实).

  1. 每个资源都需要一个唯一的标识符,即ReST中的URI.正如您已经发现的那样,在尝试更新问题中设计的子实体时,如果不这样做将会产生奇怪的影响.
  2. 您的ReSTful API应该实现超媒体约束.如果您的资源ID是URI,则无论服务器位置如何,您都可以在资源之间创建完全合格且丰富的关系.
  3. 标识符应该是不透明的.因此,永远不要在:idURI 的部分使用相关的数字或枚举.甚至不要让您的消费者尝试猜测可能暴露您不希望他们看到的内容的URI.安全性是关键,但不透明的ID是额外的.
  4. 除非有充分理由,否则标识符应由服务器生成,而不是由客户端生成.否则你的身份不会是不透明的.
  5. 根据经验:

    1. 创建POST并返回201 Created.我喜欢回应资源的主体.并且不要忘记将URI包含在创建的资源中.
    2. 阅读GET并返回200 OK.
    3. 使用修改整个资源PUT.我喜欢与post保持一致并使用a返回更新的资源200 OK.
    4. 删除DELETE并回复204 No Content.
    5. 我很少PATCH用于部分更新.

这可以让你了解大多数情况.