如何处理很多

想象一下你有两个实体, 玩家团队 ,玩家可以在多个团队中。 在我的数据模型中,我为每个实体都有一个表格,并且有一个连接表来维护关系。 Hibernate在处理这个问题上很好,但是我如何在RESTful API中公开这种关系?

我可以想到一些方法。 首先,我可能让每个实体都包含另一个实体的列表,因此一个Player对象将拥有一个它所属团队的列表,并且每个团队对象都有一个属于它的玩家列表。 因此,要将玩家添加到团队中,您只需将玩家的表示张贴到端点,如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 /playerteam

/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'        
]

最佳做法是什么?


在RESTful接口中,您可以通过将这些关系编码为链接来返回描述资源之间关系的文档。 因此,一个团队可以说是拥有一个文件资源( /team/{id}/players ),它是/team/{id}/players中球员( /player/{id} )的链接列表,并且球员可以拥有文档资源( /player/{id}/teams ),这是该玩家所属团队的链接列表。 尼斯和对称。 您可以轻松地在该列表上绘制地图操作,甚至可以给它们自己的ID(可以说它们有两个ID,这取决于您是在考虑团队优先还是玩家优先关系),如果这样可以让事情变得更容易。 唯一棘手的是你必须记得从另一端删除关系,如果你从一端删除它,但通过使用基础数据模型严格地处理这个关系,然后让REST接口成为该模型将使这更容易。

关系ID可能应该基于UUID或者同样长和随机的东西,而不管你用于团队和玩家的任何类型的ID。 这可以让你在关系的每一端使用与ID组件相同的UUID而不用担心碰撞(小整数没有这个优点)。 如果这些会员关系具有任何其他属性而不是他们以双向方式将球员和球队联系起来的事实,则他们应该具有与球员和球队无关的自己的身份; 然后可以在玩家»团队视图( /player/{playerID}/teams/{teamID} )上执行/player/{playerID}/teams/{teamID}重定向到双向视图( /memberships/{uuid} )。

我建议使用XLink xlink:href属性在您返回的任何XML文档中编写链接(如果您碰巧正在生成XML)。


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

  • 如果没有别的东西,REST就是要制作可演化的系统。 此时,你可能只关心给定的球员是否在某个特定的球队,但在未来的某个时刻,你会想用更多的数据来注释这种关系:他们在球队中的时间长短,谁转介给他们对于那支球队,他们的教练是谁,还是在那支球队等等等等。
  • REST取决于缓存的效率,这需要考虑缓存原子性和失效。 如果您向/teams/3/players/新实体/teams/3/players/该列表将失效,但您不希望替代网址/players/5/teams/保持缓存状态。 是的,不同的缓存会有不同年龄的每个列表的副本,我们可以做的事情不多,但我们至少可以通过限制我们需要失效的实体的数量来最小化用户在POST后更新的混淆。在其客户的本地缓存中只有一个在/memberships/98745 (参见Helland关于分布式事务以外的“替代索引”的讨论以获得更详细的讨论)。
  • 你可以通过简单地选择/players/5/teams/teams/3/players (但不是两者)来实现上述2点。 我们假设前者。 然而,在某些情况下,您会希望为当前会员列表保留/players/5/teams/ ,但可以在某处查看过去的会员资格。 制作/players/5/memberships/超链接列表/memberships/{id}/资源,然后您可以随时添加/players/5/past_memberships/ ,而无需为每个会员资源打破每个人的书签。 这是一个普遍的概念; 我相信你可以想象其他类似的期货更适合你的具体情况。

  • 我会将这种关系与子资源进行映射,那么通用设计/遍历就是:

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

    在Restful术语中,它没有考虑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 3
    GET /teams/3/players/3
    
    # adding player 3 also to team 2
    PUT /teams/2/players/3
    
    # getting all teams of player 3
    GET /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 yet
    POST /players
    # from payload you get back the id, now place it officially to team 1
    PUT /teams/1/players/44
    
    

    正如你所看到的,我不使用POST来将球员放置在球队中,而是使用PUT来更好地处理球员和球队之间的关系。

    链接地址: http://www.djcxy.com/p/21977.html

    上一篇: How to handle many

    下一篇: Homebrew install specific version of formula?