Implementing Dynamic Queries with Spring Data Querydsl
This article explains how to use Spring Data Querydsl to parse and execute flexible, type‑safe dynamic queries, covering request definition, Google‑like and field‑specific query formats, integration with Spring repositories, predicate building, boolean expression handling, and challenges when querying nested collections.
In this blog post, the author, a senior architect, introduces a server‑side query parsing and execution solution based on the Spring Querydsl framework.
The article first describes how query requests are structured in front‑end UI, using simple key‑value pairs such as q=keyword for Google‑like searches, and more complex field‑specific syntax like name:bill with logical operators AND and OR .
Google‑like Query
For a single search box, the query string is placed directly in the HTTP request parameter, which is easy to parse but limited for advanced filtering.
Specific Field (SQL‑like) Query
Using a colon to denote equality, queries can be composed as name:bill , name:bill AND city:LA , or name:bill OR city:LA . These require a custom parsing logic to translate into predicates.
Using Spring Data Querydsl
Querydsl provides a type‑safe API to build SQL‑like queries. Spring Data integrates it via the QuerydslPredicateExecutor interface:
public interface QuerydslPredicateExecutor
{
// Find a single entity matching the predicate
Optional
findById(Predicate predicate);
// Find all entities matching the predicate
Iterable
findAll(Predicate predicate);
// Count entities matching the predicate
long count(Predicate predicate);
// Check existence of entities matching the predicate
boolean exists(Predicate predicate);
}Repositories simply extend this interface:
interface UserRepository extends CrudRepository
, QuerydslPredicateExecutor
{}Queries are built by creating a Predicate :
Predicate predicate = user.firstname.equals("dave")
.and(user.lastname.startsWith("mathews"));
userRepository.findAll(predicate);The predicate is translated to an SQL fragment such as WHERE firstname = 'dave' AND lastname LIKE 'mathews%' , enabling flexible and readable queries.
Dynamic Query Implementation
A Student model is used as an example. Query strings like firstname:li AND lastname:hua or firstname:li OR lastname:hua AND gender:male are parsed, handling operator precedence with parentheses.
public class QueryAnalysis {
private static final String QUERY_REGEX = "([\\w.]+?)(:|<|>|!:)([^ ]*)";
// ... parsing logic that splits by AND/OR, extracts key, operation, value
}The parsing produces two containers for OR and AND conditions, which are later converted into PredicateBuilder objects.
PredicateBuilder and BooleanExpressionBuilder
PredicateBuilder collects SearchCriteria objects and builds BooleanExpression instances for each field type (String, Date, Number, Boolean). The BooleanExpressionBuilder contains methods such as getEqualBooleanExpression , getGreaterThanBooleanExpression , getContainsBooleanExpression , and conversion helpers for dates, integers, and booleans.
public class BooleanExpressionBuilder {
// ... builds predicates based on field type and operation
private BooleanExpression getEqualBooleanExpression(...){ ... }
private BooleanExpression getContainsBooleanExpression(...){ ... }
// conversion helpers for date, integer, boolean
}Challenges with Sub‑Table AND Queries
The article discusses a complex case where a parent entity (customer) has a collection of child entities (markets). A query like customerNumber:5135116903 AND markets.active:false AND markets.marketId:A1 must ensure that the AND conditions apply to the same child record, not across different elements of the collection, which requires careful predicate construction.
Finally, the author invites readers to discuss the approach, share opinions, and join a community group for further exchange.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.