我正在努力思考通过REST API将集合更新到另一个资源的最佳方法,并且正在寻找有关其他人如何看待该过程的指导。
假设您与实体“父代”(一个)和“子代”(许多)具有多对一关系。我的想法是,您可以通过单个PUT端点处理更新父级的子级集合。这样,用于更新父级的子实体并将新的子实体添加到父级集合的端点通过单个端点发生。请求主体将包含一个子实体数组,并且端点本身将包含足够的信息以了解哪个父实体正在更新:
即PUT .../ parent /{uid}/ child
端点会告诉我们,uid为{uid}的父实体是被请求的父实体,并将其更新为子实体。
这种机制让人感觉有些奇怪。即,我必须以一种方式保留新实体,并以另一种方式更新它们。我的更新/保存操作最好分批执行,但是同时进行批保存和更新感到很奇怪。我必须同时做这两项,因为您无法更新新实体
有没有更好的方法可以做到这一点?关系是分层的,这意味着没有父级,子级资源就不存在。我仍然还希望能够批量发布/发布。
我可以揭露POST与PUT的区别(使用与上述相同的端点)。我有一个约束,使得子实体具有唯一的名称,因此对于具有现有名称的POST's新的子实体,POST将必须失败,并且当请求正文包含其名称的子实体时,PUT将必须失败不存在。这就是为什么我选择与单个端点共享操作的原因。
最佳答案
与ManyToOne打交道
关于正确处理ManyToOne关系,让我解释一下,如果我要尽可能多地遵守ReST原则,我将如何做。
嵌套资源
有几种表达关系的方法,一种是您建议使用路径层次结构的方法。您将需要以下端点:
/parents/
/parents/:id
/parents/:id/children
/parents/:id/children/:id
这种选择可以更好地表达 child 无法独自生存的构图关系。
一级资源
如果要应用“超媒体”约束(应将其称为API ReSTful),则另一个选择如下:
/parents
/parents/:id
/childrens
/childrens/id
创建子资源时,您将在请求的正文中包含指向具有适当rel类型的父资源的链接。例如,如果使用HAL:
{
...
...,
"_links": {
"parent": { "href": "https://api.domain.com/parents/9283jdp92cn"}
}
}
这种选择可以更好地表达弱关系或聚合关系,关系的两端可以彼此独立地存在。
安全上下文
还有第三种选择,我们应该将其视为特例。如果父资源是经过身份验证的主体,则可以将其隐式关联到另一资源。例如,如果父级是
User
域实体,并且是Photo
集合的所有者,则您可能很想公开以下端点:/users
/users/:id
/users/:id/photos
/users/:id/photos/:id
鉴于只有
User
只能访问自己的Photo
,这就足够了:/photos
/photos/:id
因为经过身份验证的
User
通过安全上下文可用于端点,并且可以隐式建立关系,而无需通过层次结构路径或其他方式明确表示它。其他注意事项
从您的问题出发,我发现一些可能导致实现不良做法的信号。因此,这里有一些与您的帖子有关的原则,您应该尽可能遵循这些原则(务实)。
:id
部分中使用相关数字或枚举。甚至不要让您的消费者尝试猜测可能暴露您不希望他们看到的内容的URI。安全是关键,但是不透明的ID是额外的。 POST
创建并返回201 Created
。我喜欢用资源的主体来回应。并且不要忘记将URI包括到创建的资源中。 GET
并返回200 OK
。 PUT
修改整个资源。我喜欢与post保持一致,并使用200 OK
返回更新的资源。 DELETE
删除并使用204 No Content
进行响应。 PATCH
进行部分更新。 在大多数情况下,这可以使您满意。
关于java - 通过REST API处理ManyToOne实体集合的更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40311989/