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

Data filtering in Dropwizard using DAOs based on optional parameters

我想在我的 Dropwizard 服务器中实现数据过滤。假设我们要搜索纪念碑。用户可以使用名称、城市、类别等过滤器从纪念碑列表中进行过滤。

uri 看起来像 /monuments?name="Eiffel"&city"Paris"&category="Engineering Marvel"

我不清楚如何为此实现 API,因为某些用户可能会在仅指定名称过滤器后停止,而其他用户可能会使用全部 3 个。

在这种情况下,我如何在我的 DAO 中实现 Java 代码和查询以根据传递的过滤器修改查询?

我想到的和尝试过的:

1(最坏情况)- 列出这些过滤器的所有可能查询组合,并根据传递的参数组合使用一个。

2 - 我认为 JDBI 会在调用 DAO 方法时自动消除为 null 的参数,但事实并非如此,至少对于 ilike 子句(因为以上所有参数都是字符串)。

3 - 在 Postgres 中使用 Case。但这不是可扩展的,因为随着用例的增加,我可能会随着时间的推移搜索其他参数。

4 - 使用 Java 数据结构和 DAO 在内部过滤结果,例如首先根据(比方说)名称获取所有纪念碑,然后将 ID 传递给 SQL 查询与 city 子句,然后与 category 子句相同。但是随着数据的增加,这将需要很长时间来处理。

这似乎是一个相当常见的场景,但我找不到任何好的答案,大多数人谈论 URI 和 RESTful 设计而不是实现细节。

虽然@Hitobat 建议的答案在您的可选参数很少时可以正常工作,但如果您处理大量可选参数,更优雅的解决方案是考虑创建请求 pojo 并使用 Hibernate Criterias where you add a restriction 仅当参数不为空时。

请求class:

public class FilteredRequest{
    String name;
    String city;
    String category;
}

资源Class:

@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;
    }
}