Back to home

Spring JPA Dynamic Query (JDQ)

Production-ready DTO to JPA-Specification converter with multi-join support, published as Maven library

Spring JPA Dynamic Query (JDQ)

A production-ready library that simplifies the JPA Criteria API, enabling programmatic and dynamic runtime query creation. Published as a Maven artifact with 10k+ downloads.

Features

  • 9 field operators — EQUAL, NOT_EQUAL, CONTAIN, DOES_NOT_CONTAIN, START_WITH, END_WITH, GREATER_THAN, LESS_THAN, SPECIFIED (null check)
  • AND-OR conjunctions — Complex boolean logic with Criteria.OR()
  • SCOPE support — Nested parentheses for complex queries: (A OR B) AND (C OR D)
  • Single or multi JOIN — Automatic JOIN generation via dot notation (department.name)
  • Projection support — Select specific fields with alias mapping and nested object mapping
  • Pagination — Page-based results with Page<T> support
  • ORDER BY — Sort by any field, including joined columns
  • DISTINCT — Distinct result filtering
  • Query Builder — Fluent API for programmatic query construction
  • Argument Resolver — Auto-convert request parameters to DynamicQuery objects

Quick Start

Maven Dependency

<!-- Spring Boot 3.x -->
<dependency>
    <groupId>io.github.tdilber</groupId>
    <artifactId>spring-boot-starter-jpa-dynamic-query</artifactId>
    <version>0.3.0</version>
</dependency>

<!-- Spring Boot 2.x -->
<dependency>
    <groupId>io.github.tdilber</groupId>
    <artifactId>spring-jpa-dynamic-query</artifactId>
    <version>0.6.0</version>
</dependency>

Enable Annotation

@EnableJpaDynamicQuery
@SpringBootApplication
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }
}

Create Repository

public interface UserRepository extends JpaDynamicQueryRepository<User, Long> {
    // No implementation needed — all methods inherited
}

Execute Queries

// Simple WHERE clause
List<User> activeUsers = userRepository.findAll(
    CriteriaList.of(
        Criteria.of("status", CriteriaOperator.EQUAL, "ACTIVE"),
        Criteria.of("age", CriteriaOperator.GREATER_THAN, 25)
    )
);

// With JOIN
List<User> result = userRepository.findAll(
    CriteriaList.of(
        Criteria.of("department.name", CriteriaOperator.START_WITH, "Engineering")
    )
);

// With projection
List<UserSummary> summaries = userRepository.findAll(
    dynamicQuery, 
    UserSummary.class
);

Query Builder Example

Page<UserSummary> result = userRepository.queryBuilder()
    .select(Select("id", "userId"), Select("name", "userName"))
    .where(
        Field("status").eq("ACTIVE"),
        Field("age").gte(25)
    )
    .orderBy(OrderBy("name", Order.ASC))
    .page(0, 20)
    .getResultAsPage(UserSummary.class);

REST API Example

# Query with dynamic parameters
curl "http://localhost:8080/users?select0=id&select1=name&where0_key=status&where0_operation=EQUAL&where0_values0=ACTIVE&page=0&size=20"

Comparison with Traditional JPA

| Feature | Traditional JPA | JDQ | |---------|----------------|-----| | Dynamic WHERE | Manual Criteria API | Criteria.of() | | JOIN handling | Explicit @Join annotations | Dot notation field.name | | Multi-table JOIN | Complex path expressions | Automatic via annotations | | Projection | @Query with DTO | Automatic with @JdqModel | | OR logic | Specification.or() | Criteria.OR() | | SCOPE/Nesting | Manual conjunction() | CriteriaOperator.PARENTHES |

Production Usage

  • Downloaded 10k+ times via Maven Central
  • Used in production at multiple enterprises
  • 0.3.0 — Current stable version (Spring Boot 3.x)
  • 0.6.0 — Latest for Spring Boot 2.x

Resources