我想在我的Dropwizard服务器中实现数据过滤。假设我们要搜索纪念碑。用户可以使用名称,城市,类别等过滤器从古迹列表中进行过滤。
uri的外观类似于/monuments?name="Eiffel"&city"Paris"&category="Engineering Marvel"
我尚不清楚如何实现此API,因为某些用户仅在指定了名称过滤器后可能会停止,而其他用户可能会全部使用3。
在这种情况下,如何在DAO中实现Java代码和查询以基于传递了哪些过滤器来修改查询?
我想到并尝试过的事情:
1(最坏的情况)-列出这些过滤器的所有可能查询组合,并根据传递的参数组合使用一个。
2-我以为JDBI会在调用DAO方法时自动消除为空的参数,但实际上不是这样,至少使用ilike
子句(因为上述所有参数都是字符串)
3-在Postgres中使用Case。但这是不可扩展的,因为随着用例的增加,随着时间的推移,我可能还有其他参数需要搜索。
4-使用Java数据结构与DAO一起在内部过滤结果,例如首先基于(假设)名称获得所有纪念碑,然后将ID传递给带有city子句的SQL查询,然后再与category子句传递。但是随着数据的增加,这将需要很长时间来处理。
这似乎是一个相当普遍的情况,但是我对此找不到任何好的答案,大多数人谈论URI和RESTful设计而不是实现细节。
任何指导都会有所帮助。
谢谢
答案 0 :(得分:0)
虽然@Hitobat建议的答案在可选参数很少的情况下可以很好地工作,但是如果您要处理很多可选参数,则更优雅的解决方案是考虑创建请求pojo并使用Hibernate Criterias仅在参数不为空的情况下在其中添加restriction。
请求类:
public class FilteredRequest{
String name;
String city;
String category;
}
资源类别:
@GET
@Path("/monuments")
public Response searchMonuments(@ApiParam("filters") FilteredRequest filteredRequest){
return Response.ok().entity(monumentsDAO.findAll(filteredRequest)).build()
}
DAO:
public List<Monuments> class MonumentsDAO() {
public findAll(FilteredRequest filteredRequest){
Criteria criteria = getSearchCriteria(filteredRequest);
return list(criteria);
}
private Criteria getSearchCriteria(FilteredRequest filteredRequest){
Criteria criteria = criteria();
if (StringUtils.isNotEmpty(filteredRequest.getName())) {
criteria.add(Restrictions.eq("name", filteredRequest.getName()));
}
if (StringUtils.isNotEmpty(filteredRequest.getCity())) {
criteria.add(Restrictions.eq("city", filteredRequest.getCity()));
}
if (StringUtils.isNotEmpty(filteredRequest.getCategory())) {
criteria.add(Restrictions.eq("category", filteredRequest.getCategory()));
}
return criteria;
}
}