为了账号安全,请及时绑定邮箱和手机立即绑定

如何在RESTful API中处理多对多关系?

如何在RESTful API中处理多对多关系?

如何在RESTful API中处理多对多关系?想象一下,你有2个实体,玩家和团队,玩家可以在多个团队中。在我的数据模型中,我有一个每个实体的表,以及一个用于维护关系的连接表。Hibernate可以很好地处理这个问题,但是我如何在RESTful API中公开这种关系呢?我可以想几个方面。首先,我可能让每个实体都包含另一个实体的列表,因此Player对象将拥有它所属的Teams列表,并且每个Team对象都有一个属于它的Players列表。因此,要向团队添加播放器,您只需将播放器的表示形式发布到端点,例如POST /player或POST /team,并将相应的对象作为请求的有效负载。这对我来说似乎是最“RESTful”但感觉有点奇怪。/api/team/0:{     name: 'Boston Celtics',     logo: '/img/Celtics.png',     players: [         '/api/player/20',         '/api/player/5',         '/api/player/34'     ]}/api/player/20:{     pk: 20,     name: 'Ray Allen',     birth: '1975-07-20T02:00:00Z',     team: '/api/team/0'}我能想到的另一种方法就是将关系本身作为一种资源来揭露。因此,要查看给定团队中所有玩家的列表,您可以执行GET /playerteam/team/{id}或类似的操作并获取PlayerTeam实体列表。要将球员添加到球队,请/playerteam使用适当构建的PlayerTeam实体作为有效负载进行POST 。/api/team/0:{     name: 'Boston Celtics',     logo: '/img/Celtics.png'}/api/player/20:{     pk: 20,     name: 'Ray Allen',     birth: '1975-07-20T02:00:00Z',     team: '/api/team/0'}/api/player/team/0/:[     '/api/player/20',     '/api/player/5',     '/api/player/34'        ]这是什么最好的做法?
查看完整描述

3 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

制作一组单独的/memberships/资源。

  1. 如果没有别的话,REST就是要制作可进化的系统。此时,您可能只关心某个玩家是否在某个特定团队中,但在将来的某个时刻,您希望用更多数据来注释该关系:他们在该团队中待了多长时间,谁引用了他们对那个团队,他们的教练是谁/当时在那个团队等等。

  2. REST依赖于缓存效率,这需要考虑缓存原子性和失效。如果您将新实体POST到/teams/3/players/该列表将失效,但您不希望备用URL /players/5/teams/保持缓存状态。是的,不同的缓存将包含不同年龄的每个列表的副本,并且我们无法做很多事情,但我们至少可以通过限制我们需要使实体无效的实体数量来最小化用户POST更新的混淆在他们的客户端的本地缓存中唯一一个/memberships/98745(见“交替指数”的埃兰的讨论生命超越分布式事务的更详细的讨论)。

  3. 您可以通过简单地选择/players/5/teams/teams/3/players(但不是两者)来实现上述2点。让我们假设前者。但是,在某些时候,您需要保留当前成员资格/players/5/teams/的列表,并且能够在某处引用过去的成员资格。让超链接到列表中的资源,然后你可以添加当你喜欢,而不必打破大家的书签为个人会员资源。这是一般概念; 我相信你可以想象其他类似的期货更适用于你的具体情况。/players/5/memberships//memberships/{id}//players/5/past_memberships/


查看完整回答
反对 回复 2019-08-14
?
jeck猫

TA贡献1909条经验 获得超7个赞

我会将这种关系映射到子资源,一般设计/遍历将是:

# team resource/teams/{teamId}# players resource/players/{playerId}# teams/players subresource/teams/{teamId}/players/{playerId}

在Restful-terms中,它有很多不用考虑SQL和连接,而是更多地考虑集合,子集合和遍历。

一些例子:

# getting player 3 who is on team 1# or simply checking whether player 3 is on that team (200 vs. 404)GET /teams/1/players/3# getting player 3 who is also on team 3GET /teams/3/players/3# adding player 3 also to team 2PUT /teams/2/players/3# getting all teams of player 3GET /players/3/teams# withdraw player 3 from team 1 (appeared drunk before match)DELETE /teams/1/players/3# team 1 found a replacement, who is not registered in league yetPOST /players# from payload you get back the id, now place it officially to team 1PUT /teams/1/players/44

如你所见,我没有使用POST将球员放到球队,而是PUT,它可以更好地处理球员和球队的n:n关系。


查看完整回答
反对 回复 2019-08-14
  • 3 回答
  • 0 关注
  • 1091 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信