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

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

问题描述

假设您有两个实体,玩家团队,其中玩家可以在多个团队中.在我的数据模型中,每个实体都有一个表,还有一个连接表来维护关系.Hibernate 可以很好地处理这个问题,但是我如何在 <一个 href="https://en.wikipedia.org/wiki/Representational_state_transfer#RESTful_web_services" rel="noreferrer">RESTful API?

Imagine you have two 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 对象会有一个它所属的 Teams 列表,而每个 Team 对象都有一个属于它的 Players 列表.因此,要将玩家添加到团队,您只需 POST 玩家的表示到一个端点,比如 POST /player 或 POST /team ,将适当的对象作为请求的有效负载.这似乎是最RESTful"的对我来说,但感觉有点奇怪.

I can think of a couple of 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'
]

这方面的最佳做法是什么?

What is the best practice for this?

推荐答案

在 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,而不必担心冲突(小整数没有具有这种优势).如果这些成员关系除了以双向方式将球员和球队联系起来这一简单事实之外,还具有任何属性,那么它们应该具有独立于球员和球队的身份;玩家»团队视图 (/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}).

我建议使用 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天全站免登陆