在Dropwizard中使用基于可选参数的DAO进行数据过滤

时间:2018-11-25 07:11:58

标签: java filtering dropwizard jdbi

我想在我的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设计而不是实现细节。

任何指导都会有所帮助。

谢谢

1 个答案:

答案 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;
    }
}