如何在RESTful API中处理多对多关系? [英] How to handle many-to-many relationships in a RESTful API?

查看:164
本文介绍了如何在RESTful API中处理多对多关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一下,您有2个实体,玩家团队,玩家可以在多个团队中。在我的数据模型中,我为每个实体都有一个表,以及一个用于维护关系的联接表。 Hibernate非常适合处理此问题,但是如何在RESTful API中公开这种关系?

Imagine you have 2 entities, Player and Team, where players can be on multiple teams. In my data model, I have a table for each entity, and a join table to maintain the relationships. Hibernate is fine at handling this, but how might I expose this relationship in a RESTful API?

我可以想到几种方法。首先,我可能让每个实体都包含另一个实体的列表,因此,一个Player对象将具有一个它所属的团队列表,而每个Team对象将具有一个属于它的Player列表。因此,要将玩家添加到团队中,您只需将玩家的表示发布到端点,例如POST / player 或POST / team code>,并使用适当的对象作为请求的有效负载。对我来说,这似乎是最 RESTful的,但感觉有点奇怪。

I can think of a couple ways. First, I might have each entity contain a list of the other, so a Player object would have a list of Teams it belongs to, and each Team object would have a list of Players that belong to it. So to add a Player to a Team, you would just POST the player's representation to an endpoint, something like POST /player or POST /team with the appropriate object as the payload of the request. This seems the most "RESTful" to me but feels a little weird.

/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实体作为有效载荷的POST / playerteam

The other way I can think of to do this would be to expose the relationship as a resource in its own right. So to see a list of all the players on a given team, you might do a GET /playerteam/team/{id} or something like that and get back a list of PlayerTeam entities. To add a player to a team, POST /playerteam with an appropriately built PlayerTeam entity as the payload.

/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 ),该资源是指向玩家的链接列表( / player / {id} ),并且玩家可以拥有一个文档资源( / player / {id} / teams )是玩家所属团队的链接列表。尼斯和对称。您可以轻松轻松地对该列表上的地图操作进行操作,甚至可以给关系指定一个自己的ID(可以说,他们有两个ID,具体取决于您考虑的是团队优先还是玩家优先),如果这样会使事情变得更容易。唯一棘手的一点是,如果您从一端删除了该关系,则还必须记住要从另一端删除该关系,但是要通过使用基础数据模型然后使用REST接口作为视图来严格处理此关系。

In a RESTful interface, you can return documents that describe the relationships between resources by encoding those relationships as links. Thus, a team can be said to have a document resource (/team/{id}/players) that is a list of links to players (/player/{id}) on the team, and a player can have a document resource (/player/{id}/teams) that is a list of links to teams that the player is a member of. Nice and symmetric. You can the map operations on that list easily enough, even giving a relationship its own IDs (arguably they'd have two IDs, depending on whether you're thinking about the relationship team-first or player-first) if that makes things easier. The only tricky bit is that you've got to remember to delete the relationship from the other end as well if you delete it from one end, but rigorously handling this by using an underlying data model and then having the REST interface be a view of that model is going to make that easier.

关系ID可能应该基于UUID或同样漫长而随机的东西,无论您为团队使用哪种类型的ID和球员。这样一来,您就可以为关系的每一端使用与ID组件相同的UUID,而不必担心冲突(小整数 not 没有这个优点)。如果这些成员关系具有除以双向方式关联球员和团队的事实以外的任何其他属性,则它们应具有独立于球员和团队的身份;玩家»团队视图( / player / {playerID} / teams / {teamID} 上的GET可以执行HTTP重定向到双向视图( / memberships / {uuid} )。

Relationship IDs probably ought to be based on UUIDs or something equally long and random, irrespective of whatever type of IDs you use for teams and players. That will let you use the same UUID as the ID component for each end of the relationship without worrying about collisions (small integers do not have that advantage). If these membership relationships have any properties other than the bare fact that they relate a player and a team in a bidirectional fashion, they should have their own identity that is independent of both players and teams; a GET on the player»team view (/player/{playerID}/teams/{teamID}) could then do an HTTP redirect to the bidirectional view (/memberships/{uuid}).

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

I recommend writing links in any XML documents you return (if you happen to be producing XML of course) using XLink xlink:href attributes.

这篇关于如何在RESTful API中处理多对多关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆