如何为获取JPA实体的特定关系定义RESTFul Web服务API的最佳方法是什么?
示例:
如果a具有属性的用户具有属性角色(1-N关系)
我想有时候调用我的资源getUserByName(我不想因为性能而带来关系)和getUserByNameWithRoles(这里我想要关于evict双网络旅行)
使用java rest获得此功能的最佳方法是什么?
@Path("/user")
class UserResource{
@GET
@Path("/{name}")
public Response getUserByName(@PathParam("name") String name){
// hibernate query: select u from User u where u.name = :name
}
@GET
// How I map this URL?
@Path("/{name}")
public Response getUserByNameWithRoles(@PathParam("name") String name){
// hibernate query: select u from User u inner join fetch u.roles where u.name = :name
}
}
1)有2种方法吗?
2)使用一些“扩展”技巧,使用@QueryParam(确实存在任何框架,或者是手工制作)
你的家伙如何解决这个问题?
答案 0 :(得分:1)
您可以使用一个支持查询参数的方法,以便您可以加载角色:
@GET
@Path("/{name}")
@Produces("application/json")
public Response getUserByName(@PathParam("name") String name,
@QueryParam("load-roles") boolean loadRoles) {
...
}
或者,您可以让端点仅返回用户的表示,而另一个端点仅返回用户角色的表示:
@GET
@Path("/{name}")
@Produces("application/json")
public Response getUserByName(@PathParam("name") String name) {
...
}
@GET
@Path("/{name}/roles")
@Produces("application/json")
public Response getRolesFromUserByName(@PathParam("name") String name) {
...
}
当需要角色时,只需向第二个端点执行请求即可返回角色。
或者,您可以为资源的完整表示创建自定义媒体类型,并为部分表示设置自定义媒体类型。
使用这种方法,您将拥有以下方法:
@GET
@Path("/{name}")
@Produces({ "application/json", "application/vnd.company.partial+json" })
public Response getUserByName(@PathParam("name") String name) {
...
}
@GET
@Path("/{name}")
@Produces("application/vnd.company.full+json")
public Response getUserByNameWithRoles(@PathParam("name") String name) {
...
}
要请求部分代表您的资源,请求将如下:
GET /api/users/johndoe HTTP/1.1
Host: example.com
Accept: application/json
GET /api/users/johndoe HTTP/1.1
Host: example.com
Accept: application/vnd.company.partial+json
要请求资源的完整表示,请求将如下:
GET /api/users/johndoe HTTP/1.1
Host: example.com
Accept: application/vnd.company.full+json
答案 1 :(得分:0)
只需定义各种端点并调用服务或存储库类,即可在根实体上执行相应的查询,指定是否加载角色关系。
@Path("/{name}/withRoles")
public Response getUserByNameWithRoles(@PathParam("name") string name) {
User user = userRepository.findByNameWithRoles( name );
// translate your User to the response here.
}
和
@Path("/{name}")
public Response getUserByName(@PathParam("name") string name) {
User user = userRepository.findByName( name );
// translate your User to the response here.
}
在一天结束时,无论您使用框架X还是框架Y,概念和想法都保持相当直接和一致。
正如您所提到的,您可以使用@QueryParam传递一个标志,以指示是否使用或不使用角色填充User
。