Search code examples
javaspringspring-bootspring-dataquerydsl

QueryDSL: building a query from an entity


I've just started integrating QueryDSL into a Spring Boot project and I'm looking for a way to build a query out of an existing entity bean. Using @ModelAttribute it's nice and easy to pass in an entity via a GET request from the controller as long as the parameters align with the bean:

public Page<Company> getLogins(@ModelAttribute Company company, Pageable pageable, @RequestParam(value = "page", required = false) String pageNumber){
    return companyService.findbyParameters(company,pageNumber);

}

And in the service class, I can use the BooleanBuilder to build up a query:

    public Page<Company> findbyParameters(Company companySearch,String pageNumber){
        QCompany company = QCompany.company;
        BooleanBuilder builder = new BooleanBuilder();
        if (companySearch.getEmail() != null && !companySearch.getEmail().equals("")){
            builder.and(company.email.eq(companySearch.getEmail()));
        }
        if (companySearch.getCompanyName() != null && !companySearch.getCompanyName().equals("")){
            builder.and(company.companyName.eq(companySearch.getCompanyName()));
        }
       //add other clauses...
       return loginRepository.findAll(builder.getValue(),pageableService.getPageRequest(pageNumber));
    }

..and this works fine. But it seems like an unnecessary amount of plumbing since I'll have to write similar, longwinded conditional code for each entity I'm working with. I reckon that reflection might be an option, but I'm not sure if QueryDSL has something built in that handles this situation. I've looked at the QueryDSL docs and nothing jumped out at me.

So is there a nice, tidy way of handling this situation without clogging up my service classes with boilerplate?


Solution

  • It turns out that the exact thing I was looking for is Spring Data's query by example API.

    https://www.baeldung.com/spring-data-query-by-example

    It lets you create a query by providing a sample entity and a matcher which defines things like case sensitivity, partial 'like' matching and so on.

    It's very useful in limited situations, and can drastically reduce boilerplate query code; but when you want to query a more complex graph of data you'll want to use a different approach.