使用JPA Hibernate实体定义Rest API – LAZY和EAGER
如何为获取JPA实体的特定关系定义RESTFul Web服务API的最佳方法是什么?
例:
如果一个资源用户具有属性角色(1-N关系)
我想有时候调用我的资源getUserByName(我不想因为性能带来关系)和getUserByNameWithRoles(这里我想要关于evict双网络旅行)
如何通过javarest获得此function的最佳方法是什么?
@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(确实存在任何框架,或者它是手动的)
你的家伙怎么解决这个问题?
使用查询参数
您可以使用一个支持查询参数的方法来为您提供加载角色的可能性:
@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
只需定义各种端点并调用服务或存储库类,即可在指定是否加载角色关系的根实体上执行相应的查询。
@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
。